server.c revision 171577
1139749Simp/* 226159Sse * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") 326159Sse * Copyright (C) 1999-2003 Internet Software Consortium. 426159Sse * 526159Sse * Permission to use, copy, modify, and distribute this software for any 626159Sse * purpose with or without fee is hereby granted, provided that the above 726159Sse * copyright notice and this permission notice appear in all copies. 826159Sse * 926159Sse * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 1026159Sse * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1126159Sse * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 1226159Sse * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 1326159Sse * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 1426159Sse * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 1526159Sse * PERFORMANCE OF THIS SOFTWARE. 1626159Sse */ 1726159Sse 1826159Sse/* $Id: server.c,v 1.419.18.49.12.2 2007/07/09 02:23:16 marka Exp $ */ 1926159Sse 2026159Sse/*! \file */ 2126159Sse 2226159Sse#include <config.h> 2326159Sse 2426159Sse#include <stdlib.h> 2526159Sse 2650477Speter#include <isc/app.h> 2726159Sse#include <isc/base64.h> 2826159Sse#include <isc/dir.h> 296100Sse#include <isc/entropy.h> 3039231Sgibbs#include <isc/file.h> 31165217Sjhb#include <isc/hash.h> 3239231Sgibbs#include <isc/lex.h> 3339231Sgibbs#include <isc/parseint.h> 3439231Sgibbs#include <isc/print.h> 3526159Sse#include <isc/resource.h> 36165217Sjhb#include <isc/stdio.h> 37165217Sjhb#include <isc/string.h> 38165217Sjhb#include <isc/task.h> 396100Sse#include <isc/timer.h> 40163805Simp#include <isc/util.h> 416100Sse 42120063Sscottl#include <isccfg/namedconf.h> 43120063Sscottl 44120063Sscottl#include <bind9/check.h> 45214122Sjkim 46214122Sjkim#include <dns/acache.h> 47214122Sjkim#include <dns/adb.h> 48120063Sscottl#include <dns/cache.h> 49220195Sjhb#include <dns/db.h> 50220195Sjhb#include <dns/dispatch.h> 51220195Sjhb#ifdef DLZ 52220195Sjhb#include <dns/dlz.h> 53220195Sjhb#endif 54220195Sjhb#include <dns/forward.h> 55220195Sjhb#include <dns/journal.h> 56220195Sjhb#include <dns/keytable.h> 57163163Sjmg#include <dns/lib.h> 58163163Sjmg#include <dns/master.h> 59163163Sjmg#include <dns/masterdump.h> 60262134Sjhb#include <dns/order.h> 61163163Sjmg#include <dns/peer.h> 62163163Sjmg#include <dns/portlist.h> 63163163Sjmg#include <dns/rdataclass.h> 64163163Sjmg#include <dns/rdataset.h> 65163163Sjmg#include <dns/rdatastruct.h> 66163163Sjmg#include <dns/resolver.h> 67163163Sjmg#include <dns/rootns.h> 68163163Sjmg#include <dns/secalg.h> 69163163Sjmg#include <dns/stats.h> 70163163Sjmg#include <dns/tkey.h> 71163163Sjmg#include <dns/view.h> 72167909Sjhb#include <dns/zone.h> 73163163Sjmg#include <dns/zt.h> 74163163Sjmg 75163163Sjmg#include <dst/dst.h> 76163163Sjmg#include <dst/result.h> 77163163Sjmg 78163163Sjmg#include <named/client.h> 79163163Sjmg#include <named/config.h> 80120063Sscottl#include <named/control.h> 81120063Sscottl#include <named/interfacemgr.h> 82120063Sscottl#include <named/log.h> 83164264Sjhb#include <named/logconf.h> 84120063Sscottl#include <named/lwresd.h> 85164264Sjhb#include <named/main.h> 86164264Sjhb#include <named/os.h> 87164264Sjhb#include <named/server.h> 88169221Sjhb#include <named/tkeyconf.h> 89120063Sscottl#include <named/tsigconf.h> 90120063Sscottl#include <named/zoneconf.h> 91164282Sjhb#ifdef HAVE_LIBSCF 92169221Sjhb#include <named/ns_smf_globals.h> 93169221Sjhb#include <stdlib.h> 94169221Sjhb#endif 95169221Sjhb 96169221Sjhb/*% 97169221Sjhb * Check an operation for failure. Assumes that the function 98169221Sjhb * using it has a 'result' variable and a 'cleanup' label. 99169221Sjhb */ 100169221Sjhb#define CHECK(op) \ 101169221Sjhb do { result = (op); \ 102169221Sjhb if (result != ISC_R_SUCCESS) goto cleanup; \ 103164264Sjhb } while (0) 104164264Sjhb 105169221Sjhb#define CHECKM(op, msg) \ 106164282Sjhb do { result = (op); \ 107164264Sjhb if (result != ISC_R_SUCCESS) { \ 108164264Sjhb isc_log_write(ns_g_lctx, \ 109164264Sjhb NS_LOGCATEGORY_GENERAL, \ 110164264Sjhb NS_LOGMODULE_SERVER, \ 111169221Sjhb ISC_LOG_ERROR, \ 112169221Sjhb "%s: %s", msg, \ 113169221Sjhb isc_result_totext(result)); \ 114169221Sjhb goto cleanup; \ 115164264Sjhb } \ 116164264Sjhb } while (0) \ 117164264Sjhb 118164264Sjhb#define CHECKMF(op, msg, file) \ 119180753Sluoqi do { result = (op); \ 120180753Sluoqi if (result != ISC_R_SUCCESS) { \ 121219737Sjhb isc_log_write(ns_g_lctx, \ 122180753Sluoqi NS_LOGCATEGORY_GENERAL, \ 123180753Sluoqi NS_LOGMODULE_SERVER, \ 124180753Sluoqi ISC_LOG_ERROR, \ 125180753Sluoqi "%s '%s': %s", msg, file, \ 126180753Sluoqi isc_result_totext(result)); \ 12726159Sse goto cleanup; \ 12826159Sse } \ 12945720Speter } while (0) \ 1306100Sse 131220195Sjhb#define CHECKFATAL(op, msg) \ 132128019Simp do { result = (op); \ 133119266Simp if (result != ISC_R_SUCCESS) \ 134119266Simp fatal(msg, result); \ 135119266Simp } while (0) \ 136119266Simp 1376100Ssestruct ns_dispatch { 138119266Simp isc_sockaddr_t addr; 139119266Simp unsigned int dispatchgen; 1407233Sse dns_dispatch_t *dispatch; 141119266Simp ISC_LINK(struct ns_dispatch) link; 142119266Simp}; 143119266Simp 144119266Simpstruct dumpcontext { 1456100Sse isc_mem_t *mctx; 146119266Simp isc_boolean_t dumpcache; 147119266Simp isc_boolean_t dumpzones; 148119266Simp FILE *fp; 149119266Simp ISC_LIST(struct viewlistentry) viewlist; 1506100Sse struct viewlistentry *view; 151119266Simp struct zonelistentry *zone; 152119266Simp dns_dumpctx_t *mdctx; 153119266Simp dns_db_t *db; 1546100Sse dns_db_t *cache; 155119266Simp isc_task_t *task; 156119266Simp dns_dbversion_t *version; 1577233Sse}; 158172394Smarius 159119266Simpstruct viewlistentry { 160119266Simp dns_view_t *view; 161119266Simp ISC_LINK(struct viewlistentry) link; 1627233Sse ISC_LIST(struct zonelistentry) zonelist; 163193256Sjhb}; 164193256Sjhb 165193256Sjhbstruct zonelistentry { 166193256Sjhb dns_zone_t *zone; 167180753Sluoqi ISC_LINK(struct zonelistentry) link; 16826159Sse}; 1696100Sse 17026159Sse/* 1716100Sse * These zones should not leak onto the Internet. 172165217Sjhb */ 173165217Sjhbstatic const struct { 174165217Sjhb const char *zone; 175165217Sjhb isc_boolean_t rfc1918; 1767233Sse} empty_zones[] = { 17726159Sse#ifdef notyet 17826159Sse /* RFC 1918 */ 17926159Sse { "10.IN-ADDR.ARPA", ISC_TRUE }, 180119266Simp { "16.172.IN-ADDR.ARPA", ISC_TRUE }, 181119266Simp { "17.172.IN-ADDR.ARPA", ISC_TRUE }, 182119266Simp { "18.172.IN-ADDR.ARPA", ISC_TRUE }, 183119266Simp { "19.172.IN-ADDR.ARPA", ISC_TRUE }, 184119266Simp { "20.172.IN-ADDR.ARPA", ISC_TRUE }, 185119266Simp { "21.172.IN-ADDR.ARPA", ISC_TRUE }, 186119266Simp { "22.172.IN-ADDR.ARPA", ISC_TRUE }, 18726159Sse { "23.172.IN-ADDR.ARPA", ISC_TRUE }, 1886100Sse { "24.172.IN-ADDR.ARPA", ISC_TRUE }, 18926159Sse { "25.172.IN-ADDR.ARPA", ISC_TRUE }, 19026159Sse { "26.172.IN-ADDR.ARPA", ISC_TRUE }, 19126159Sse { "27.172.IN-ADDR.ARPA", ISC_TRUE }, 192119266Simp { "28.172.IN-ADDR.ARPA", ISC_TRUE }, 193119266Simp { "29.172.IN-ADDR.ARPA", ISC_TRUE }, 194119266Simp { "30.172.IN-ADDR.ARPA", ISC_TRUE }, 195119266Simp { "31.172.IN-ADDR.ARPA", ISC_TRUE }, 196119266Simp { "168.192.IN-ADDR.ARPA", ISC_TRUE }, 197119266Simp#endif 198119266Simp 199119266Simp /* RFC 3330 */ 200119266Simp { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */ 201119266Simp { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */ 202119266Simp { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */ 203119266Simp { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */ 20426159Sse 20526159Sse /* Local IPv6 Unicast Addresses */ 206119266Simp { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE }, 20739231Sgibbs { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE }, 20861047Speter /* LOCALLY ASSIGNED LOCAL ADDRES S SCOPE */ 20961047Speter { "D.F.IP6.ARPA", ISC_FALSE }, 21061047Speter { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 21161047Speter { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 21261047Speter { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 21361047Speter { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ 21461047Speter 21561047Speter { NULL, ISC_FALSE } 21661047Speter}; 21739231Sgibbs 21845720Speterstatic void 21945720Speterfatal(const char *msg, isc_result_t result); 22045720Speter 22145720Speterstatic void 22245720Speterns_server_reload(isc_task_t *task, isc_event_t *event); 22369953Smsmith 22469953Smsmithstatic isc_result_t 22569953Smsmithns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 22669953Smsmith cfg_aclconfctx_t *actx, 22769953Smsmith isc_mem_t *mctx, ns_listenelt_t **target); 22869953Smsmithstatic isc_result_t 22969953Smsmithns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 23069953Smsmith cfg_aclconfctx_t *actx, 23169953Smsmith isc_mem_t *mctx, ns_listenlist_t **target); 23269953Smsmith 23369953Smsmithstatic isc_result_t 234172394Smariusconfigure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 23569953Smsmith const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype); 23669953Smsmith 23769953Smsmithstatic isc_result_t 238107300Simpconfigure_alternates(const cfg_obj_t *config, dns_view_t *view, 239149972Simp const cfg_obj_t *alternates); 240149972Simp 241149972Simpstatic isc_result_t 242149972Simpconfigure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 243178161Sphk const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 24445720Speter cfg_aclconfctx_t *aclconf); 24545720Speter 24645720Speterstatic void 24745720Speterend_reserved_dispatches(ns_server_t *server, isc_boolean_t all); 24845720Speter 249165217Sjhb/*% 25088375Stmm * Configure a single view ACL at '*aclp'. Get its configuration by 25145720Speter * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl' 252119266Simp * (for a global default). 253119266Simp */ 254119266Simpstatic isc_result_t 255119266Simpconfigure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, 256119266Simp const char *aclname, cfg_aclconfctx_t *actx, 257119266Simp isc_mem_t *mctx, dns_acl_t **aclp) 258119266Simp{ 259119266Simp isc_result_t result; 260119266Simp const cfg_obj_t *maps[3]; 261119266Simp const cfg_obj_t *aclobj = NULL; 262119266Simp int i = 0; 263172394Smarius 264119266Simp if (*aclp != NULL) 265119266Simp dns_acl_detach(aclp); 266119266Simp if (vconfig != NULL) 267119266Simp maps[i++] = cfg_tuple_get(vconfig, "options"); 268149972Simp if (config != NULL) { 269149972Simp const cfg_obj_t *options = NULL; 270149972Simp (void)cfg_map_get(config, "options", &options); 271149972Simp if (options != NULL) 272149972Simp maps[i++] = options; 27345720Speter } 27466416Speter maps[i] = NULL; 27566416Speter 27669953Smsmith (void)ns_config_get(maps, aclname, &aclobj); 27769953Smsmith if (aclobj == NULL) 27869953Smsmith /* 279119266Simp * No value available. *aclp == NULL. 28045720Speter */ 28145720Speter return (ISC_R_SUCCESS); 28245720Speter 28345720Speter result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, 28445720Speter actx, mctx, aclp); 28545720Speter 286119266Simp return (result); 28745720Speter} 28845720Speter 28945720Speterstatic isc_result_t 29045720Speterconfigure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, 29147339Sgallatin dns_keytable_t *keytable, isc_mem_t *mctx) 29247339Sgallatin{ 29347339Sgallatin dns_rdataclass_t viewclass; 29447339Sgallatin dns_rdata_dnskey_t keystruct; 29547339Sgallatin isc_uint32_t flags, proto, alg; 29647339Sgallatin const char *keystr, *keynamestr; 297172394Smarius unsigned char keydata[4096]; 29865176Sdfr isc_buffer_t keydatabuf; 29947339Sgallatin unsigned char rrdata[4096]; 30047339Sgallatin isc_buffer_t rrdatabuf; 301165217Sjhb isc_region_t r; 302102144Smux dns_fixedname_t fkeyname; 30347339Sgallatin dns_name_t *keyname; 304172394Smarius isc_buffer_t namebuf; 305119266Simp isc_result_t result; 30647339Sgallatin dst_key_t *dstkey = NULL; 30766416Speter 30866416Speter flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); 30969953Smsmith proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); 31098017Simp alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); 31198017Simp keyname = dns_fixedname_name(&fkeyname); 31298017Simp keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 31390554Smsmith 314165217Sjhb if (vconfig == NULL) 315165217Sjhb viewclass = dns_rdataclass_in; 31690554Smsmith else { 31790554Smsmith const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); 31869953Smsmith CHECK(ns_config_getclass(classobj, dns_rdataclass_in, 31969953Smsmith &viewclass)); 32069953Smsmith } 32169953Smsmith keystruct.common.rdclass = viewclass; 32269953Smsmith keystruct.common.rdtype = dns_rdatatype_dnskey; 323113544Smdodd /* 32473185Speter * The key data in keystruct is not dynamically allocated. 32573185Speter */ 326113544Smdodd keystruct.mctx = NULL; 32773185Speter 32845720Speter ISC_LINK_INIT(&keystruct.common, link); 329113544Smdodd 33073185Speter if (flags > 0xffff) 33173185Speter CHECKM(ISC_R_RANGE, "key flags"); 332113544Smdodd if (proto > 0xff) 33373185Speter CHECKM(ISC_R_RANGE, "key protocol"); 33473185Speter if (alg > 0xff) 335113544Smdodd CHECKM(ISC_R_RANGE, "key algorithm"); 33673185Speter keystruct.flags = (isc_uint16_t)flags; 33773185Speter keystruct.protocol = (isc_uint8_t)proto; 338113544Smdodd keystruct.algorithm = (isc_uint8_t)alg; 33973185Speter 34073185Speter isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); 341113544Smdodd isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 34273185Speter 34373185Speter keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); 344113544Smdodd CHECK(isc_base64_decodestring(keystr, &keydatabuf)); 34573185Speter isc_buffer_usedregion(&keydatabuf, &r); 34673185Speter keystruct.datalen = r.length; 347163163Sjmg keystruct.data = r.base; 348163163Sjmg 349163163Sjmg if ((keystruct.algorithm == DST_ALG_RSASHA1 || 350163163Sjmg keystruct.algorithm == DST_ALG_RSAMD5) && 351163163Sjmg r.length > 1 && r.base[0] == 1 && r.base[1] == 3) 352163163Sjmg cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, 353163163Sjmg "trusted key '%s' has a weak exponent", 354163163Sjmg keynamestr); 355163163Sjmg 356163163Sjmg CHECK(dns_rdata_fromstruct(NULL, 357163163Sjmg keystruct.common.rdclass, 358163163Sjmg keystruct.common.rdtype, 35969953Smsmith &keystruct, &rrdatabuf)); 360145651Smarcel dns_fixedname_init(&fkeyname); 361145651Smarcel isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); 362145651Smarcel isc_buffer_add(&namebuf, strlen(keynamestr)); 363145651Smarcel CHECK(dns_name_fromtext(keyname, &namebuf, 364145651Smarcel dns_rootname, ISC_FALSE, 365145651Smarcel NULL)); 366145651Smarcel CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, 367145651Smarcel mctx, &dstkey)); 368145651Smarcel 369145651Smarcel CHECK(dns_keytable_add(keytable, &dstkey)); 370145651Smarcel INSIST(dstkey == NULL); 371145651Smarcel return (ISC_R_SUCCESS); 372145651Smarcel 373145651Smarcel cleanup: 374145651Smarcel if (result == DST_R_NOCRYPTO) { 375145651Smarcel cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 376145651Smarcel "ignoring trusted key for '%s': no crypto support", 377145651Smarcel keynamestr); 37869953Smsmith result = ISC_R_SUCCESS; 37969953Smsmith } else { 38069953Smsmith cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, 38169953Smsmith "configuring trusted key for '%s': %s", 38269953Smsmith keynamestr, isc_result_totext(result)); 38369953Smsmith result = ISC_R_FAILURE; 384160964Syar } 38569953Smsmith 38669953Smsmith if (dstkey != NULL) 387160964Syar dst_key_free(&dstkey); 38869953Smsmith 38969953Smsmith return (result); 39069953Smsmith} 39169953Smsmith 392165217Sjhb/*% 393165217Sjhb * Configure DNSSEC keys for a view. Currently used only for 394165217Sjhb * the security roots. 395165217Sjhb * 396165217Sjhb * The per-view configuration values and the server-global defaults are read 39726159Sse * from 'vconfig' and 'config'. The variable to be configured is '*target'. 39873185Speter */ 39973185Speterstatic isc_result_t 40073185Speterconfigure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config, 40173185Speter isc_mem_t *mctx, dns_keytable_t **target) 40273185Speter{ 40358287Speter isc_result_t result; 40473185Speter const cfg_obj_t *keys = NULL; 40573185Speter const cfg_obj_t *voptions = NULL; 40673185Speter const cfg_listelt_t *element, *element2; 40773185Speter const cfg_obj_t *keylist; 40873185Speter const cfg_obj_t *key; 40973185Speter dns_keytable_t *keytable = NULL; 410153560Sjhb 411219865Sjhb CHECK(dns_keytable_create(mctx, &keytable)); 412219865Sjhb 413219865Sjhb if (vconfig != NULL) 414219865Sjhb voptions = cfg_tuple_get(vconfig, "options"); 415219865Sjhb 416219865Sjhb keys = NULL; 417153560Sjhb if (voptions != NULL) 418153560Sjhb (void)cfg_map_get(voptions, "trusted-keys", &keys); 419219865Sjhb if (keys == NULL) 420153560Sjhb (void)cfg_map_get(config, "trusted-keys", &keys); 421153560Sjhb 422164264Sjhb for (element = cfg_list_first(keys); 423164264Sjhb element != NULL; 424164264Sjhb element = cfg_list_next(element)) 425164264Sjhb { 426164264Sjhb keylist = cfg_listelt_value(element); 427164264Sjhb for (element2 = cfg_list_first(keylist); 428164264Sjhb element2 != NULL; 429166176Sjhb element2 = cfg_list_next(element2)) 430166176Sjhb { 431166176Sjhb key = cfg_listelt_value(element2); 432166176Sjhb CHECK(configure_view_dnsseckey(vconfig, key, 433166176Sjhb keytable, mctx)); 434166176Sjhb } 435169221Sjhb } 436166176Sjhb 437169221Sjhb dns_keytable_detach(target); 438166176Sjhb *target = keytable; /* Transfer ownership. */ 439166176Sjhb keytable = NULL; 440166176Sjhb result = ISC_R_SUCCESS; 441164264Sjhb 442164264Sjhb cleanup: 443164264Sjhb return (result); 444164264Sjhb} 445164264Sjhb 446164264Sjhbstatic isc_result_t 447164264Sjhbmustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) 448164264Sjhb{ 449164264Sjhb const cfg_listelt_t *element; 450164264Sjhb const cfg_obj_t *obj; 451164264Sjhb const char *str; 452166176Sjhb dns_fixedname_t fixed; 453166176Sjhb dns_name_t *name; 454166176Sjhb isc_boolean_t value; 455166176Sjhb isc_result_t result; 456166176Sjhb isc_buffer_t b; 457166176Sjhb 458119266Simp dns_fixedname_init(&fixed); 459172394Smarius name = dns_fixedname_name(&fixed); 460119266Simp for (element = cfg_list_first(mbs); 461223885Skib element != NULL; 462164264Sjhb element = cfg_list_next(element)) 463169221Sjhb { 464164264Sjhb obj = cfg_listelt_value(element); 465169221Sjhb str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); 466165228Sjhb isc_buffer_init(&b, str, strlen(str)); 467253273Smarius isc_buffer_add(&b, strlen(str)); 468164264Sjhb CHECK(dns_name_fromtext(name, &b, dns_rootname, 469180753Sluoqi ISC_FALSE, NULL)); 470180753Sluoqi value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); 471203528Smav CHECK(dns_resolver_setmustbesecure(resolver, name, value)); 472233379Sjhb } 473233379Sjhb 474203528Smav result = ISC_R_SUCCESS; 475203528Smav 47669953Smsmith cleanup: 47761047Speter return (result); 47869953Smsmith} 47969953Smsmith 48069953Smsmith/*% 48169953Smsmith * Get a dispatch appropriate for the resolver of a given view. 48258287Speter */ 48369953Smsmithstatic isc_result_t 48469953Smsmithget_view_querysource_dispatch(const cfg_obj_t **maps, 48569953Smsmith int af, dns_dispatch_t **dispatchp) 48688184Smdodd{ 48712453Sbde isc_result_t result; 48888184Smdodd dns_dispatch_t *disp; 489119266Simp isc_sockaddr_t sa; 49088184Smdodd unsigned int attrs, attrmask; 491220195Sjhb const cfg_obj_t *obj = NULL; 492220195Sjhb 493262134Sjhb /* 494220195Sjhb * Make compiler happy. 495261622Sdumbbell */ 496261622Sdumbbell result = ISC_R_FAILURE; 497261622Sdumbbell 498261622Sdumbbell switch (af) { 499261622Sdumbbell case AF_INET: 500261622Sdumbbell result = ns_config_get(maps, "query-source", &obj); 501261622Sdumbbell INSIST(result == ISC_R_SUCCESS); 50239231Sgibbs break; 503 case AF_INET6: 504 result = ns_config_get(maps, "query-source-v6", &obj); 505 INSIST(result == ISC_R_SUCCESS); 506 break; 507 default: 508 INSIST(0); 509 } 510 511 sa = *(cfg_obj_assockaddr(obj)); 512 INSIST(isc_sockaddr_pf(&sa) == af); 513 514 /* 515 * If we don't support this address family, we're done! 516 */ 517 switch (af) { 518 case AF_INET: 519 result = isc_net_probeipv4(); 520 break; 521 case AF_INET6: 522 result = isc_net_probeipv6(); 523 break; 524 default: 525 INSIST(0); 526 } 527 if (result != ISC_R_SUCCESS) 528 return (ISC_R_SUCCESS); 529 530 /* 531 * Try to find a dispatcher that we can share. 532 */ 533 attrs = 0; 534 attrs |= DNS_DISPATCHATTR_UDP; 535 switch (af) { 536 case AF_INET: 537 attrs |= DNS_DISPATCHATTR_IPV4; 538 break; 539 case AF_INET6: 540 attrs |= DNS_DISPATCHATTR_IPV6; 541 break; 542 } 543 attrmask = 0; 544 attrmask |= DNS_DISPATCHATTR_UDP; 545 attrmask |= DNS_DISPATCHATTR_TCP; 546 attrmask |= DNS_DISPATCHATTR_IPV4; 547 attrmask |= DNS_DISPATCHATTR_IPV6; 548 549 disp = NULL; 550 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 551 ns_g_taskmgr, &sa, 4096, 552 1000, 32768, 16411, 16433, 553 attrs, attrmask, &disp); 554 if (result != ISC_R_SUCCESS) { 555 isc_sockaddr_t any; 556 char buf[ISC_SOCKADDR_FORMATSIZE]; 557 558 switch (af) { 559 case AF_INET: 560 isc_sockaddr_any(&any); 561 break; 562 case AF_INET6: 563 isc_sockaddr_any6(&any); 564 break; 565 } 566 if (isc_sockaddr_equal(&sa, &any)) 567 return (ISC_R_SUCCESS); 568 isc_sockaddr_format(&sa, buf, sizeof(buf)); 569 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 570 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 571 "could not get query source dispatcher (%s)", 572 buf); 573 return (result); 574 } 575 576 *dispatchp = disp; 577 578 return (ISC_R_SUCCESS); 579} 580 581static isc_result_t 582configure_order(dns_order_t *order, const cfg_obj_t *ent) { 583 dns_rdataclass_t rdclass; 584 dns_rdatatype_t rdtype; 585 const cfg_obj_t *obj; 586 dns_fixedname_t fixed; 587 unsigned int mode = 0; 588 const char *str; 589 isc_buffer_t b; 590 isc_result_t result; 591 isc_boolean_t addroot; 592 593 result = ns_config_getclass(cfg_tuple_get(ent, "class"), 594 dns_rdataclass_any, &rdclass); 595 if (result != ISC_R_SUCCESS) 596 return (result); 597 598 result = ns_config_gettype(cfg_tuple_get(ent, "type"), 599 dns_rdatatype_any, &rdtype); 600 if (result != ISC_R_SUCCESS) 601 return (result); 602 603 obj = cfg_tuple_get(ent, "name"); 604 if (cfg_obj_isstring(obj)) 605 str = cfg_obj_asstring(obj); 606 else 607 str = "*"; 608 addroot = ISC_TF(strcmp(str, "*") == 0); 609 isc_buffer_init(&b, str, strlen(str)); 610 isc_buffer_add(&b, strlen(str)); 611 dns_fixedname_init(&fixed); 612 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, 613 dns_rootname, ISC_FALSE, NULL); 614 if (result != ISC_R_SUCCESS) 615 return (result); 616 617 obj = cfg_tuple_get(ent, "ordering"); 618 INSIST(cfg_obj_isstring(obj)); 619 str = cfg_obj_asstring(obj); 620 if (!strcasecmp(str, "fixed")) 621 mode = DNS_RDATASETATTR_FIXEDORDER; 622 else if (!strcasecmp(str, "random")) 623 mode = DNS_RDATASETATTR_RANDOMIZE; 624 else if (!strcasecmp(str, "cyclic")) 625 mode = 0; 626 else 627 INSIST(0); 628 629 /* 630 * "*" should match everything including the root (BIND 8 compat). 631 * As dns_name_matcheswildcard(".", "*.") returns FALSE add a 632 * explicit entry for "." when the name is "*". 633 */ 634 if (addroot) { 635 result = dns_order_add(order, dns_rootname, 636 rdtype, rdclass, mode); 637 if (result != ISC_R_SUCCESS) 638 return (result); 639 } 640 641 return (dns_order_add(order, dns_fixedname_name(&fixed), 642 rdtype, rdclass, mode)); 643} 644 645static isc_result_t 646configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { 647 isc_netaddr_t na; 648 dns_peer_t *peer; 649 const cfg_obj_t *obj; 650 const char *str; 651 isc_result_t result; 652 unsigned int prefixlen; 653 654 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); 655 656 peer = NULL; 657 result = dns_peer_new(mctx, &na, &peer); 658 if (result != ISC_R_SUCCESS) 659 return (result); 660 661 obj = NULL; 662 (void)cfg_map_get(cpeer, "bogus", &obj); 663 if (obj != NULL) 664 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj))); 665 666 obj = NULL; 667 (void)cfg_map_get(cpeer, "provide-ixfr", &obj); 668 if (obj != NULL) 669 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj))); 670 671 obj = NULL; 672 (void)cfg_map_get(cpeer, "request-ixfr", &obj); 673 if (obj != NULL) 674 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj))); 675 676 obj = NULL; 677 (void)cfg_map_get(cpeer, "edns", &obj); 678 if (obj != NULL) 679 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj))); 680 681 obj = NULL; 682 (void)cfg_map_get(cpeer, "edns-udp-size", &obj); 683 if (obj != NULL) { 684 isc_uint32_t udpsize = cfg_obj_asuint32(obj); 685 if (udpsize < 512) 686 udpsize = 512; 687 if (udpsize > 4096) 688 udpsize = 4096; 689 CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize)); 690 } 691 692 obj = NULL; 693 (void)cfg_map_get(cpeer, "max-udp-size", &obj); 694 if (obj != NULL) { 695 isc_uint32_t udpsize = cfg_obj_asuint32(obj); 696 if (udpsize < 512) 697 udpsize = 512; 698 if (udpsize > 4096) 699 udpsize = 4096; 700 CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize)); 701 } 702 703 obj = NULL; 704 (void)cfg_map_get(cpeer, "transfers", &obj); 705 if (obj != NULL) 706 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj))); 707 708 obj = NULL; 709 (void)cfg_map_get(cpeer, "transfer-format", &obj); 710 if (obj != NULL) { 711 str = cfg_obj_asstring(obj); 712 if (strcasecmp(str, "many-answers") == 0) 713 CHECK(dns_peer_settransferformat(peer, 714 dns_many_answers)); 715 else if (strcasecmp(str, "one-answer") == 0) 716 CHECK(dns_peer_settransferformat(peer, 717 dns_one_answer)); 718 else 719 INSIST(0); 720 } 721 722 obj = NULL; 723 (void)cfg_map_get(cpeer, "keys", &obj); 724 if (obj != NULL) { 725 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj)); 726 if (result != ISC_R_SUCCESS) 727 goto cleanup; 728 } 729 730 obj = NULL; 731 if (na.family == AF_INET) 732 (void)cfg_map_get(cpeer, "transfer-source", &obj); 733 else 734 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); 735 if (obj != NULL) { 736 result = dns_peer_settransfersource(peer, 737 cfg_obj_assockaddr(obj)); 738 if (result != ISC_R_SUCCESS) 739 goto cleanup; 740 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 741 } 742 743 obj = NULL; 744 if (na.family == AF_INET) 745 (void)cfg_map_get(cpeer, "notify-source", &obj); 746 else 747 (void)cfg_map_get(cpeer, "notify-source-v6", &obj); 748 if (obj != NULL) { 749 result = dns_peer_setnotifysource(peer, 750 cfg_obj_assockaddr(obj)); 751 if (result != ISC_R_SUCCESS) 752 goto cleanup; 753 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 754 } 755 756 obj = NULL; 757 if (na.family == AF_INET) 758 (void)cfg_map_get(cpeer, "query-source", &obj); 759 else 760 (void)cfg_map_get(cpeer, "query-source-v6", &obj); 761 if (obj != NULL) { 762 result = dns_peer_setquerysource(peer, 763 cfg_obj_assockaddr(obj)); 764 if (result != ISC_R_SUCCESS) 765 goto cleanup; 766 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); 767 } 768 769 *peerp = peer; 770 return (ISC_R_SUCCESS); 771 772 cleanup: 773 dns_peer_detach(&peer); 774 return (result); 775} 776 777static isc_result_t 778disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { 779 isc_result_t result; 780 const cfg_obj_t *algorithms; 781 const cfg_listelt_t *element; 782 const char *str; 783 dns_fixedname_t fixed; 784 dns_name_t *name; 785 isc_buffer_t b; 786 787 dns_fixedname_init(&fixed); 788 name = dns_fixedname_name(&fixed); 789 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); 790 isc_buffer_init(&b, str, strlen(str)); 791 isc_buffer_add(&b, strlen(str)); 792 CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL)); 793 794 algorithms = cfg_tuple_get(disabled, "algorithms"); 795 for (element = cfg_list_first(algorithms); 796 element != NULL; 797 element = cfg_list_next(element)) 798 { 799 isc_textregion_t r; 800 dns_secalg_t alg; 801 802 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base); 803 r.length = strlen(r.base); 804 805 result = dns_secalg_fromtext(&alg, &r); 806 if (result != ISC_R_SUCCESS) { 807 isc_uint8_t ui; 808 result = isc_parse_uint8(&ui, r.base, 10); 809 alg = ui; 810 } 811 if (result != ISC_R_SUCCESS) { 812 cfg_obj_log(cfg_listelt_value(element), 813 ns_g_lctx, ISC_LOG_ERROR, 814 "invalid algorithm"); 815 CHECK(result); 816 } 817 CHECK(dns_resolver_disable_algorithm(resolver, name, alg)); 818 } 819 cleanup: 820 return (result); 821} 822 823static isc_boolean_t 824on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { 825 const cfg_listelt_t *element; 826 dns_fixedname_t fixed; 827 dns_name_t *name; 828 isc_result_t result; 829 const cfg_obj_t *value; 830 const char *str; 831 isc_buffer_t b; 832 833 dns_fixedname_init(&fixed); 834 name = dns_fixedname_name(&fixed); 835 836 for (element = cfg_list_first(disablelist); 837 element != NULL; 838 element = cfg_list_next(element)) 839 { 840 value = cfg_listelt_value(element); 841 str = cfg_obj_asstring(value); 842 isc_buffer_init(&b, str, strlen(str)); 843 isc_buffer_add(&b, strlen(str)); 844 result = dns_name_fromtext(name, &b, dns_rootname, 845 ISC_TRUE, NULL); 846 RUNTIME_CHECK(result == ISC_R_SUCCESS); 847 if (dns_name_equal(name, zonename)) 848 return (ISC_TRUE); 849 } 850 return (ISC_FALSE); 851} 852 853static void 854check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv, 855 isc_mem_t *mctx) 856{ 857 char **argv = NULL; 858 unsigned int i; 859 isc_result_t result; 860 861 result = dns_zone_getdbtype(*zonep, &argv, mctx); 862 if (result != ISC_R_SUCCESS) { 863 dns_zone_detach(zonep); 864 return; 865 } 866 867 /* 868 * Check that all the arguments match. 869 */ 870 for (i = 0; i < dbtypec; i++) 871 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) { 872 dns_zone_detach(zonep); 873 break; 874 } 875 876 /* 877 * Check that there are not extra arguments. 878 */ 879 if (i == dbtypec && argv[i] != NULL) 880 dns_zone_detach(zonep); 881 isc_mem_free(mctx, argv); 882} 883 884 885/* 886 * Configure 'view' according to 'vconfig', taking defaults from 'config' 887 * where values are missing in 'vconfig'. 888 * 889 * When configuring the default view, 'vconfig' will be NULL and the 890 * global defaults in 'config' used exclusively. 891 */ 892static isc_result_t 893configure_view(dns_view_t *view, const cfg_obj_t *config, 894 const cfg_obj_t *vconfig, isc_mem_t *mctx, 895 cfg_aclconfctx_t *actx, isc_boolean_t need_hints) 896{ 897 const cfg_obj_t *maps[4]; 898 const cfg_obj_t *cfgmaps[3]; 899 const cfg_obj_t *options = NULL; 900 const cfg_obj_t *voptions = NULL; 901 const cfg_obj_t *forwardtype; 902 const cfg_obj_t *forwarders; 903 const cfg_obj_t *alternates; 904 const cfg_obj_t *zonelist; 905#ifdef DLZ 906 const cfg_obj_t *dlz; 907 unsigned int dlzargc; 908 char **dlzargv; 909#endif 910 const cfg_obj_t *disabled; 911 const cfg_obj_t *obj; 912 const cfg_listelt_t *element; 913 in_port_t port; 914 dns_cache_t *cache = NULL; 915 isc_result_t result; 916 isc_uint32_t max_adb_size; 917 isc_uint32_t max_cache_size; 918 isc_uint32_t max_acache_size; 919 isc_uint32_t lame_ttl; 920 dns_tsig_keyring_t *ring; 921 dns_view_t *pview = NULL; /* Production view */ 922 isc_mem_t *cmctx; 923 dns_dispatch_t *dispatch4 = NULL; 924 dns_dispatch_t *dispatch6 = NULL; 925 isc_boolean_t reused_cache = ISC_FALSE; 926 int i; 927 const char *str; 928 dns_order_t *order = NULL; 929 isc_uint32_t udpsize; 930 unsigned int check = 0; 931 dns_zone_t *zone = NULL; 932 isc_uint32_t max_clients_per_query; 933 const char *sep = ": view "; 934 const char *viewname = view->name; 935 const char *forview = " for view "; 936 isc_boolean_t rfc1918; 937 isc_boolean_t empty_zones_enable; 938 const cfg_obj_t *disablelist = NULL; 939 940 REQUIRE(DNS_VIEW_VALID(view)); 941 942 cmctx = NULL; 943 944 if (config != NULL) 945 (void)cfg_map_get(config, "options", &options); 946 947 i = 0; 948 if (vconfig != NULL) { 949 voptions = cfg_tuple_get(vconfig, "options"); 950 maps[i++] = voptions; 951 } 952 if (options != NULL) 953 maps[i++] = options; 954 maps[i++] = ns_g_defaults; 955 maps[i] = NULL; 956 957 i = 0; 958 if (voptions != NULL) 959 cfgmaps[i++] = voptions; 960 if (config != NULL) 961 cfgmaps[i++] = config; 962 cfgmaps[i] = NULL; 963 964 if (!strcmp(viewname, "_default")) { 965 sep = ""; 966 viewname = ""; 967 forview = ""; 968 } 969 970 /* 971 * Set the view's port number for outgoing queries. 972 */ 973 CHECKM(ns_config_getport(config, &port), "port"); 974 dns_view_setdstport(view, port); 975 976 /* 977 * Create additional cache for this view and zones under the view 978 * if explicitly enabled. 979 * XXX950 default to on. 980 */ 981 obj = NULL; 982 (void)ns_config_get(maps, "acache-enable", &obj); 983 if (obj != NULL && cfg_obj_asboolean(obj)) { 984 cmctx = NULL; 985 CHECK(isc_mem_create(0, 0, &cmctx)); 986 CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr, 987 ns_g_timermgr)); 988 isc_mem_detach(&cmctx); 989 } 990 if (view->acache != NULL) { 991 obj = NULL; 992 result = ns_config_get(maps, "acache-cleaning-interval", &obj); 993 INSIST(result == ISC_R_SUCCESS); 994 dns_acache_setcleaninginterval(view->acache, 995 cfg_obj_asuint32(obj) * 60); 996 997 obj = NULL; 998 result = ns_config_get(maps, "max-acache-size", &obj); 999 INSIST(result == ISC_R_SUCCESS); 1000 if (cfg_obj_isstring(obj)) { 1001 str = cfg_obj_asstring(obj); 1002 INSIST(strcasecmp(str, "unlimited") == 0); 1003 max_acache_size = ISC_UINT32_MAX; 1004 } else { 1005 isc_resourcevalue_t value; 1006 1007 value = cfg_obj_asuint64(obj); 1008 if (value > ISC_UINT32_MAX) { 1009 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 1010 "'max-acache-size " 1011 "%" ISC_PRINT_QUADFORMAT 1012 "d' is too large", 1013 value); 1014 result = ISC_R_RANGE; 1015 goto cleanup; 1016 } 1017 max_acache_size = (isc_uint32_t)value; 1018 } 1019 dns_acache_setcachesize(view->acache, max_acache_size); 1020 } 1021 1022 /* 1023 * Configure the zones. 1024 */ 1025 zonelist = NULL; 1026 if (voptions != NULL) 1027 (void)cfg_map_get(voptions, "zone", &zonelist); 1028 else 1029 (void)cfg_map_get(config, "zone", &zonelist); 1030 for (element = cfg_list_first(zonelist); 1031 element != NULL; 1032 element = cfg_list_next(element)) 1033 { 1034 const cfg_obj_t *zconfig = cfg_listelt_value(element); 1035 CHECK(configure_zone(config, zconfig, vconfig, mctx, view, 1036 actx)); 1037 } 1038 1039#ifdef DLZ 1040 /* 1041 * Create Dynamically Loadable Zone driver. 1042 */ 1043 dlz = NULL; 1044 if (voptions != NULL) 1045 (void)cfg_map_get(voptions, "dlz", &dlz); 1046 else 1047 (void)cfg_map_get(config, "dlz", &dlz); 1048 1049 obj = NULL; 1050 if (dlz != NULL) { 1051 (void)cfg_map_get(cfg_tuple_get(dlz, "options"), 1052 "database", &obj); 1053 if (obj != NULL) { 1054 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); 1055 if (s == NULL) { 1056 result = ISC_R_NOMEMORY; 1057 goto cleanup; 1058 } 1059 1060 result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv); 1061 if (result != ISC_R_SUCCESS) { 1062 isc_mem_free(mctx, s); 1063 goto cleanup; 1064 } 1065 1066 obj = cfg_tuple_get(dlz, "name"); 1067 result = dns_dlzcreate(mctx, cfg_obj_asstring(obj), 1068 dlzargv[0], dlzargc, dlzargv, 1069 &view->dlzdatabase); 1070 isc_mem_free(mctx, s); 1071 isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv)); 1072 if (result != ISC_R_SUCCESS) 1073 goto cleanup; 1074 } 1075 } 1076#endif 1077 1078 /* 1079 * Configure the view's cache. Try to reuse an existing 1080 * cache if possible, otherwise create a new cache. 1081 * Note that the ADB is not preserved in either case. 1082 * 1083 * XXX Determining when it is safe to reuse a cache is 1084 * tricky. When the view's configuration changes, the cached 1085 * data may become invalid because it reflects our old 1086 * view of the world. As more view attributes become 1087 * configurable, we will have to add code here to check 1088 * whether they have changed in ways that could 1089 * invalidate the cache. 1090 */ 1091 result = dns_viewlist_find(&ns_g_server->viewlist, 1092 view->name, view->rdclass, 1093 &pview); 1094 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 1095 goto cleanup; 1096 if (pview != NULL) { 1097 INSIST(pview->cache != NULL); 1098 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1099 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3), 1100 "reusing existing cache"); 1101 reused_cache = ISC_TRUE; 1102 dns_cache_attach(pview->cache, &cache); 1103 dns_view_detach(&pview); 1104 } else { 1105 CHECK(isc_mem_create(0, 0, &cmctx)); 1106 CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr, 1107 view->rdclass, "rbt", 0, NULL, &cache)); 1108 } 1109 dns_view_setcache(view, cache); 1110 1111 /* 1112 * cache-file cannot be inherited if views are present, but this 1113 * should be caught by the configuration checking stage. 1114 */ 1115 obj = NULL; 1116 result = ns_config_get(maps, "cache-file", &obj); 1117 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) { 1118 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj))); 1119 if (!reused_cache) 1120 CHECK(dns_cache_load(cache)); 1121 } 1122 1123 obj = NULL; 1124 result = ns_config_get(maps, "cleaning-interval", &obj); 1125 INSIST(result == ISC_R_SUCCESS); 1126 dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60); 1127 1128 obj = NULL; 1129 result = ns_config_get(maps, "max-cache-size", &obj); 1130 INSIST(result == ISC_R_SUCCESS); 1131 if (cfg_obj_isstring(obj)) { 1132 str = cfg_obj_asstring(obj); 1133 INSIST(strcasecmp(str, "unlimited") == 0); 1134 max_cache_size = ISC_UINT32_MAX; 1135 } else { 1136 isc_resourcevalue_t value; 1137 value = cfg_obj_asuint64(obj); 1138 if (value > ISC_UINT32_MAX) { 1139 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 1140 "'max-cache-size " 1141 "%" ISC_PRINT_QUADFORMAT "d' is too large", 1142 value); 1143 result = ISC_R_RANGE; 1144 goto cleanup; 1145 } 1146 max_cache_size = (isc_uint32_t)value; 1147 } 1148 dns_cache_setcachesize(cache, max_cache_size); 1149 1150 dns_cache_detach(&cache); 1151 1152 /* 1153 * Check-names. 1154 */ 1155 obj = NULL; 1156 result = ns_checknames_get(maps, "response", &obj); 1157 INSIST(result == ISC_R_SUCCESS); 1158 1159 str = cfg_obj_asstring(obj); 1160 if (strcasecmp(str, "fail") == 0) { 1161 check = DNS_RESOLVER_CHECKNAMES | 1162 DNS_RESOLVER_CHECKNAMESFAIL; 1163 view->checknames = ISC_TRUE; 1164 } else if (strcasecmp(str, "warn") == 0) { 1165 check = DNS_RESOLVER_CHECKNAMES; 1166 view->checknames = ISC_FALSE; 1167 } else if (strcasecmp(str, "ignore") == 0) { 1168 check = 0; 1169 view->checknames = ISC_FALSE; 1170 } else 1171 INSIST(0); 1172 1173 /* 1174 * Resolver. 1175 * 1176 * XXXRTH Hardwired number of tasks. 1177 */ 1178 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4)); 1179 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6)); 1180 if (dispatch4 == NULL && dispatch6 == NULL) { 1181 UNEXPECTED_ERROR(__FILE__, __LINE__, 1182 "unable to obtain neither an IPv4 nor" 1183 " an IPv6 dispatch"); 1184 result = ISC_R_UNEXPECTED; 1185 goto cleanup; 1186 } 1187 CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, 1188 ns_g_socketmgr, ns_g_timermgr, 1189 check, ns_g_dispatchmgr, 1190 dispatch4, dispatch6)); 1191 1192 /* 1193 * Set the ADB cache size to 1/8th of the max-cache-size. 1194 */ 1195 max_adb_size = 0; 1196 if (max_cache_size != 0) { 1197 max_adb_size = max_cache_size / 8; 1198 if (max_adb_size == 0) 1199 max_adb_size = 1; /* Force minimum. */ 1200 } 1201 dns_adb_setadbsize(view->adb, max_adb_size); 1202 1203 /* 1204 * Set resolver's lame-ttl. 1205 */ 1206 obj = NULL; 1207 result = ns_config_get(maps, "lame-ttl", &obj); 1208 INSIST(result == ISC_R_SUCCESS); 1209 lame_ttl = cfg_obj_asuint32(obj); 1210 if (lame_ttl > 1800) 1211 lame_ttl = 1800; 1212 dns_resolver_setlamettl(view->resolver, lame_ttl); 1213 1214 obj = NULL; 1215 result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj); 1216 INSIST(result == ISC_R_SUCCESS); 1217 dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj)); 1218 1219 /* 1220 * Set the resolver's EDNS UDP size. 1221 */ 1222 obj = NULL; 1223 result = ns_config_get(maps, "edns-udp-size", &obj); 1224 INSIST(result == ISC_R_SUCCESS); 1225 udpsize = cfg_obj_asuint32(obj); 1226 if (udpsize < 512) 1227 udpsize = 512; 1228 if (udpsize > 4096) 1229 udpsize = 4096; 1230 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize); 1231 1232 /* 1233 * Set the maximum UDP response size. 1234 */ 1235 obj = NULL; 1236 result = ns_config_get(maps, "max-udp-size", &obj); 1237 INSIST(result == ISC_R_SUCCESS); 1238 udpsize = cfg_obj_asuint32(obj); 1239 if (udpsize < 512) 1240 udpsize = 512; 1241 if (udpsize > 4096) 1242 udpsize = 4096; 1243 view->maxudp = udpsize; 1244 1245 /* 1246 * Set supported DNSSEC algorithms. 1247 */ 1248 dns_resolver_reset_algorithms(view->resolver); 1249 disabled = NULL; 1250 (void)ns_config_get(maps, "disable-algorithms", &disabled); 1251 if (disabled != NULL) { 1252 for (element = cfg_list_first(disabled); 1253 element != NULL; 1254 element = cfg_list_next(element)) 1255 CHECK(disable_algorithms(cfg_listelt_value(element), 1256 view->resolver)); 1257 } 1258 1259 /* 1260 * A global or view "forwarders" option, if present, 1261 * creates an entry for "." in the forwarding table. 1262 */ 1263 forwardtype = NULL; 1264 forwarders = NULL; 1265 (void)ns_config_get(maps, "forward", &forwardtype); 1266 (void)ns_config_get(maps, "forwarders", &forwarders); 1267 if (forwarders != NULL) 1268 CHECK(configure_forward(config, view, dns_rootname, 1269 forwarders, forwardtype)); 1270 1271 /* 1272 * Dual Stack Servers. 1273 */ 1274 alternates = NULL; 1275 (void)ns_config_get(maps, "dual-stack-servers", &alternates); 1276 if (alternates != NULL) 1277 CHECK(configure_alternates(config, view, alternates)); 1278 1279 /* 1280 * We have default hints for class IN if we need them. 1281 */ 1282 if (view->rdclass == dns_rdataclass_in && view->hints == NULL) 1283 dns_view_sethints(view, ns_g_server->in_roothints); 1284 1285 /* 1286 * If we still have no hints, this is a non-IN view with no 1287 * "hints zone" configured. Issue a warning, except if this 1288 * is a root server. Root servers never need to consult 1289 * their hints, so it's no point requiring users to configure 1290 * them. 1291 */ 1292 if (view->hints == NULL) { 1293 dns_zone_t *rootzone = NULL; 1294 (void)dns_view_findzone(view, dns_rootname, &rootzone); 1295 if (rootzone != NULL) { 1296 dns_zone_detach(&rootzone); 1297 need_hints = ISC_FALSE; 1298 } 1299 if (need_hints) 1300 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1301 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1302 "no root hints for view '%s'", 1303 view->name); 1304 } 1305 1306 /* 1307 * Configure the view's TSIG keys. 1308 */ 1309 ring = NULL; 1310 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring)); 1311 dns_view_setkeyring(view, ring); 1312 1313 /* 1314 * Configure the view's peer list. 1315 */ 1316 { 1317 const cfg_obj_t *peers = NULL; 1318 const cfg_listelt_t *element; 1319 dns_peerlist_t *newpeers = NULL; 1320 1321 (void)ns_config_get(cfgmaps, "server", &peers); 1322 CHECK(dns_peerlist_new(mctx, &newpeers)); 1323 for (element = cfg_list_first(peers); 1324 element != NULL; 1325 element = cfg_list_next(element)) 1326 { 1327 const cfg_obj_t *cpeer = cfg_listelt_value(element); 1328 dns_peer_t *peer; 1329 1330 CHECK(configure_peer(cpeer, mctx, &peer)); 1331 dns_peerlist_addpeer(newpeers, peer); 1332 dns_peer_detach(&peer); 1333 } 1334 dns_peerlist_detach(&view->peers); 1335 view->peers = newpeers; /* Transfer ownership. */ 1336 } 1337 1338 /* 1339 * Configure the views rrset-order. 1340 */ 1341 { 1342 const cfg_obj_t *rrsetorder = NULL; 1343 const cfg_listelt_t *element; 1344 1345 (void)ns_config_get(maps, "rrset-order", &rrsetorder); 1346 CHECK(dns_order_create(mctx, &order)); 1347 for (element = cfg_list_first(rrsetorder); 1348 element != NULL; 1349 element = cfg_list_next(element)) 1350 { 1351 const cfg_obj_t *ent = cfg_listelt_value(element); 1352 1353 CHECK(configure_order(order, ent)); 1354 } 1355 if (view->order != NULL) 1356 dns_order_detach(&view->order); 1357 dns_order_attach(order, &view->order); 1358 dns_order_detach(&order); 1359 } 1360 /* 1361 * Copy the aclenv object. 1362 */ 1363 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv); 1364 1365 /* 1366 * Configure the "match-clients" and "match-destinations" ACL. 1367 */ 1368 CHECK(configure_view_acl(vconfig, config, "match-clients", actx, 1369 ns_g_mctx, &view->matchclients)); 1370 CHECK(configure_view_acl(vconfig, config, "match-destinations", actx, 1371 ns_g_mctx, &view->matchdestinations)); 1372 1373 /* 1374 * Configure the "match-recursive-only" option. 1375 */ 1376 obj = NULL; 1377 (void)ns_config_get(maps, "match-recursive-only", &obj); 1378 if (obj != NULL && cfg_obj_asboolean(obj)) 1379 view->matchrecursiveonly = ISC_TRUE; 1380 else 1381 view->matchrecursiveonly = ISC_FALSE; 1382 1383 /* 1384 * Configure other configurable data. 1385 */ 1386 obj = NULL; 1387 result = ns_config_get(maps, "recursion", &obj); 1388 INSIST(result == ISC_R_SUCCESS); 1389 view->recursion = cfg_obj_asboolean(obj); 1390 1391 obj = NULL; 1392 result = ns_config_get(maps, "auth-nxdomain", &obj); 1393 INSIST(result == ISC_R_SUCCESS); 1394 view->auth_nxdomain = cfg_obj_asboolean(obj); 1395 1396 obj = NULL; 1397 result = ns_config_get(maps, "minimal-responses", &obj); 1398 INSIST(result == ISC_R_SUCCESS); 1399 view->minimalresponses = cfg_obj_asboolean(obj); 1400 1401 obj = NULL; 1402 result = ns_config_get(maps, "transfer-format", &obj); 1403 INSIST(result == ISC_R_SUCCESS); 1404 str = cfg_obj_asstring(obj); 1405 if (strcasecmp(str, "many-answers") == 0) 1406 view->transfer_format = dns_many_answers; 1407 else if (strcasecmp(str, "one-answer") == 0) 1408 view->transfer_format = dns_one_answer; 1409 else 1410 INSIST(0); 1411 1412 /* 1413 * Set sources where additional data and CNAME/DNAME 1414 * targets for authoritative answers may be found. 1415 */ 1416 obj = NULL; 1417 result = ns_config_get(maps, "additional-from-auth", &obj); 1418 INSIST(result == ISC_R_SUCCESS); 1419 view->additionalfromauth = cfg_obj_asboolean(obj); 1420 if (view->recursion && ! view->additionalfromauth) { 1421 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1422 "'additional-from-auth no' is only supported " 1423 "with 'recursion no'"); 1424 view->additionalfromauth = ISC_TRUE; 1425 } 1426 1427 obj = NULL; 1428 result = ns_config_get(maps, "additional-from-cache", &obj); 1429 INSIST(result == ISC_R_SUCCESS); 1430 view->additionalfromcache = cfg_obj_asboolean(obj); 1431 if (view->recursion && ! view->additionalfromcache) { 1432 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 1433 "'additional-from-cache no' is only supported " 1434 "with 'recursion no'"); 1435 view->additionalfromcache = ISC_TRUE; 1436 } 1437 1438 /* 1439 * Set "allow-query-cache" and "allow-recursion" acls if 1440 * configured in named.conf. 1441 */ 1442 CHECK(configure_view_acl(vconfig, config, "allow-query-cache", 1443 actx, ns_g_mctx, &view->queryacl)); 1444 1445 if (strcmp(view->name, "_bind") != 0) 1446 CHECK(configure_view_acl(vconfig, config, "allow-recursion", 1447 actx, ns_g_mctx, &view->recursionacl)); 1448 1449 /* 1450 * Warning if both "recursion no;" and allow-recursion are active 1451 * except for "allow-recursion { none; };". 1452 */ 1453 if (!view->recursion && view->recursionacl != NULL && 1454 (view->recursionacl->length != 1 || 1455 view->recursionacl->elements[0].type != dns_aclelementtype_any || 1456 view->recursionacl->elements[0].negative != ISC_TRUE)) 1457 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1458 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 1459 "both \"recursion no;\" and \"allow-recursion\" " 1460 "active%s%s", forview, viewname); 1461 1462 /* 1463 * "allow-query-cache" inherits from "allow-recursion" if set, 1464 * otherwise from "allow-query" if set. 1465 * "allow-recursion" inherits from "allow-query-cache" if set, 1466 * otherwise from "allow-query" if set. 1467 */ 1468 if (view->queryacl == NULL && view->recursionacl != NULL) 1469 dns_acl_attach(view->recursionacl, &view->queryacl); 1470 if (view->queryacl == NULL) 1471 CHECK(configure_view_acl(vconfig, config, "allow-query", 1472 actx, ns_g_mctx, &view->queryacl)); 1473 if (view->recursionacl == NULL && view->queryacl != NULL) 1474 dns_acl_attach(view->queryacl, &view->recursionacl); 1475 1476 /* 1477 * Set default "allow-recursion" and "allow-query-cache" acls. 1478 */ 1479 if (view->recursionacl == NULL && view->recursion) 1480 CHECK(configure_view_acl(NULL, ns_g_config, "allow-recursion", 1481 actx, ns_g_mctx, &view->recursionacl)); 1482 if (view->queryacl == NULL) 1483 CHECK(configure_view_acl(NULL, ns_g_config, 1484 "allow-query-cache", actx, 1485 ns_g_mctx, &view->queryacl)); 1486 1487 CHECK(configure_view_acl(vconfig, config, "sortlist", 1488 actx, ns_g_mctx, &view->sortlist)); 1489 1490 obj = NULL; 1491 result = ns_config_get(maps, "request-ixfr", &obj); 1492 INSIST(result == ISC_R_SUCCESS); 1493 view->requestixfr = cfg_obj_asboolean(obj); 1494 1495 obj = NULL; 1496 result = ns_config_get(maps, "provide-ixfr", &obj); 1497 INSIST(result == ISC_R_SUCCESS); 1498 view->provideixfr = cfg_obj_asboolean(obj); 1499 1500 obj = NULL; 1501 result = ns_config_get(maps, "max-clients-per-query", &obj); 1502 INSIST(result == ISC_R_SUCCESS); 1503 max_clients_per_query = cfg_obj_asuint32(obj); 1504 1505 obj = NULL; 1506 result = ns_config_get(maps, "clients-per-query", &obj); 1507 INSIST(result == ISC_R_SUCCESS); 1508 dns_resolver_setclientsperquery(view->resolver, 1509 cfg_obj_asuint32(obj), 1510 max_clients_per_query); 1511 1512 obj = NULL; 1513 result = ns_config_get(maps, "dnssec-enable", &obj); 1514 INSIST(result == ISC_R_SUCCESS); 1515 view->enablednssec = cfg_obj_asboolean(obj); 1516 1517 obj = NULL; 1518 result = ns_config_get(maps, "dnssec-accept-expired", &obj); 1519 INSIST(result == ISC_R_SUCCESS); 1520 view->acceptexpired = cfg_obj_asboolean(obj); 1521 1522 obj = NULL; 1523 result = ns_config_get(maps, "dnssec-validation", &obj); 1524 INSIST(result == ISC_R_SUCCESS); 1525 view->enablevalidation = cfg_obj_asboolean(obj); 1526 1527 obj = NULL; 1528 result = ns_config_get(maps, "dnssec-lookaside", &obj); 1529 if (result == ISC_R_SUCCESS) { 1530 for (element = cfg_list_first(obj); 1531 element != NULL; 1532 element = cfg_list_next(element)) 1533 { 1534 const char *str; 1535 isc_buffer_t b; 1536 dns_name_t *dlv; 1537 1538 obj = cfg_listelt_value(element); 1539#if 0 1540 dns_fixedname_t fixed; 1541 dns_name_t *name; 1542 1543 /* 1544 * When we support multiple dnssec-lookaside 1545 * entries this is how to find the domain to be 1546 * checked. XXXMPA 1547 */ 1548 dns_fixedname_init(&fixed); 1549 name = dns_fixedname_name(&fixed); 1550 str = cfg_obj_asstring(cfg_tuple_get(obj, 1551 "domain")); 1552 isc_buffer_init(&b, str, strlen(str)); 1553 isc_buffer_add(&b, strlen(str)); 1554 CHECK(dns_name_fromtext(name, &b, dns_rootname, 1555 ISC_TRUE, NULL)); 1556#endif 1557 str = cfg_obj_asstring(cfg_tuple_get(obj, 1558 "trust-anchor")); 1559 isc_buffer_init(&b, str, strlen(str)); 1560 isc_buffer_add(&b, strlen(str)); 1561 dlv = dns_fixedname_name(&view->dlv_fixed); 1562 CHECK(dns_name_fromtext(dlv, &b, dns_rootname, 1563 ISC_TRUE, NULL)); 1564 view->dlv = dns_fixedname_name(&view->dlv_fixed); 1565 } 1566 } else 1567 view->dlv = NULL; 1568 1569 /* 1570 * For now, there is only one kind of trusted keys, the 1571 * "security roots". 1572 */ 1573 CHECK(configure_view_dnsseckeys(vconfig, config, mctx, 1574 &view->secroots)); 1575 dns_resolver_resetmustbesecure(view->resolver); 1576 obj = NULL; 1577 result = ns_config_get(maps, "dnssec-must-be-secure", &obj); 1578 if (result == ISC_R_SUCCESS) 1579 CHECK(mustbesecure(obj, view->resolver)); 1580 1581 obj = NULL; 1582 result = ns_config_get(maps, "max-cache-ttl", &obj); 1583 INSIST(result == ISC_R_SUCCESS); 1584 view->maxcachettl = cfg_obj_asuint32(obj); 1585 1586 obj = NULL; 1587 result = ns_config_get(maps, "max-ncache-ttl", &obj); 1588 INSIST(result == ISC_R_SUCCESS); 1589 view->maxncachettl = cfg_obj_asuint32(obj); 1590 if (view->maxncachettl > 7 * 24 * 3600) 1591 view->maxncachettl = 7 * 24 * 3600; 1592 1593 obj = NULL; 1594 result = ns_config_get(maps, "preferred-glue", &obj); 1595 if (result == ISC_R_SUCCESS) { 1596 str = cfg_obj_asstring(obj); 1597 if (strcasecmp(str, "a") == 0) 1598 view->preferred_glue = dns_rdatatype_a; 1599 else if (strcasecmp(str, "aaaa") == 0) 1600 view->preferred_glue = dns_rdatatype_aaaa; 1601 else 1602 view->preferred_glue = 0; 1603 } else 1604 view->preferred_glue = 0; 1605 1606 obj = NULL; 1607 result = ns_config_get(maps, "root-delegation-only", &obj); 1608 if (result == ISC_R_SUCCESS) { 1609 dns_view_setrootdelonly(view, ISC_TRUE); 1610 if (!cfg_obj_isvoid(obj)) { 1611 dns_fixedname_t fixed; 1612 dns_name_t *name; 1613 isc_buffer_t b; 1614 const char *str; 1615 const cfg_obj_t *exclude; 1616 1617 dns_fixedname_init(&fixed); 1618 name = dns_fixedname_name(&fixed); 1619 for (element = cfg_list_first(obj); 1620 element != NULL; 1621 element = cfg_list_next(element)) { 1622 exclude = cfg_listelt_value(element); 1623 str = cfg_obj_asstring(exclude); 1624 isc_buffer_init(&b, str, strlen(str)); 1625 isc_buffer_add(&b, strlen(str)); 1626 CHECK(dns_name_fromtext(name, &b, dns_rootname, 1627 ISC_FALSE, NULL)); 1628 CHECK(dns_view_excludedelegationonly(view, 1629 name)); 1630 } 1631 } 1632 } else 1633 dns_view_setrootdelonly(view, ISC_FALSE); 1634 1635 /* 1636 * Setup automatic empty zones. If recursion is off then 1637 * they are disabled by default. 1638 */ 1639 obj = NULL; 1640 (void)ns_config_get(maps, "empty-zones-enable", &obj); 1641 (void)ns_config_get(maps, "disable-empty-zone", &disablelist); 1642 if (obj == NULL && disablelist == NULL && 1643 view->rdclass == dns_rdataclass_in) { 1644 rfc1918 = ISC_FALSE; 1645 empty_zones_enable = view->recursion; 1646 } else if (view->rdclass == dns_rdataclass_in) { 1647 rfc1918 = ISC_TRUE; 1648 if (obj != NULL) 1649 empty_zones_enable = cfg_obj_asboolean(obj); 1650 else 1651 empty_zones_enable = view->recursion; 1652 } else { 1653 rfc1918 = ISC_FALSE; 1654 empty_zones_enable = ISC_FALSE; 1655 } 1656 if (empty_zones_enable) { 1657 const char *empty; 1658 int empty_zone = 0; 1659 dns_fixedname_t fixed; 1660 dns_name_t *name; 1661 isc_buffer_t buffer; 1662 const char *str; 1663 char server[DNS_NAME_FORMATSIZE + 1]; 1664 char contact[DNS_NAME_FORMATSIZE + 1]; 1665 isc_boolean_t logit; 1666 const char *empty_dbtype[4] = 1667 { "_builtin", "empty", NULL, NULL }; 1668 int empty_dbtypec = 4; 1669 1670 dns_fixedname_init(&fixed); 1671 name = dns_fixedname_name(&fixed); 1672 1673 obj = NULL; 1674 result = ns_config_get(maps, "empty-server", &obj); 1675 if (result == ISC_R_SUCCESS) { 1676 str = cfg_obj_asstring(obj); 1677 isc_buffer_init(&buffer, str, strlen(str)); 1678 isc_buffer_add(&buffer, strlen(str)); 1679 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1680 ISC_FALSE, NULL)); 1681 isc_buffer_init(&buffer, server, sizeof(server) - 1); 1682 CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); 1683 server[isc_buffer_usedlength(&buffer)] = 0; 1684 empty_dbtype[2] = server; 1685 } else 1686 empty_dbtype[2] = "@"; 1687 1688 obj = NULL; 1689 result = ns_config_get(maps, "empty-contact", &obj); 1690 if (result == ISC_R_SUCCESS) { 1691 str = cfg_obj_asstring(obj); 1692 isc_buffer_init(&buffer, str, strlen(str)); 1693 isc_buffer_add(&buffer, strlen(str)); 1694 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1695 ISC_FALSE, NULL)); 1696 isc_buffer_init(&buffer, contact, sizeof(contact) - 1); 1697 CHECK(dns_name_totext(name, ISC_FALSE, &buffer)); 1698 contact[isc_buffer_usedlength(&buffer)] = 0; 1699 empty_dbtype[3] = contact; 1700 } else 1701 empty_dbtype[3] = "."; 1702 1703 logit = ISC_TRUE; 1704 for (empty = empty_zones[empty_zone].zone; 1705 empty != NULL; 1706 empty = empty_zones[++empty_zone].zone) 1707 { 1708 dns_forwarders_t *forwarders = NULL; 1709 dns_view_t *pview = NULL; 1710 1711 isc_buffer_init(&buffer, empty, strlen(empty)); 1712 isc_buffer_add(&buffer, strlen(empty)); 1713 /* 1714 * Look for zone on drop list. 1715 */ 1716 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1717 ISC_FALSE, NULL)); 1718 if (disablelist != NULL && 1719 on_disable_list(disablelist, name)) 1720 continue; 1721 1722 /* 1723 * This zone already exists. 1724 */ 1725 (void)dns_view_findzone(view, name, &zone); 1726 if (zone != NULL) { 1727 dns_zone_detach(&zone); 1728 continue; 1729 } 1730 1731 /* 1732 * If we would forward this name don't add a 1733 * empty zone for it. 1734 */ 1735 result = dns_fwdtable_find(view->fwdtable, name, 1736 &forwarders); 1737 if (result == ISC_R_SUCCESS && 1738 forwarders->fwdpolicy == dns_fwdpolicy_only) 1739 continue; 1740 1741 if (!rfc1918 && empty_zones[empty_zone].rfc1918) { 1742 if (logit) { 1743 isc_log_write(ns_g_lctx, 1744 NS_LOGCATEGORY_GENERAL, 1745 NS_LOGMODULE_SERVER, 1746 ISC_LOG_WARNING, 1747 "Warning%s%s: " 1748 "'empty-zones-enable/" 1749 "disable-empty-zone' " 1750 "not set: disabling " 1751 "RFC 1918 empty zones", 1752 sep, viewname); 1753 logit = ISC_FALSE; 1754 } 1755 continue; 1756 } 1757 1758 /* 1759 * See if we can re-use a existing zone. 1760 */ 1761 result = dns_viewlist_find(&ns_g_server->viewlist, 1762 view->name, view->rdclass, 1763 &pview); 1764 if (result != ISC_R_NOTFOUND && 1765 result != ISC_R_SUCCESS) 1766 goto cleanup; 1767 1768 if (pview != NULL) { 1769 (void)dns_view_findzone(pview, name, &zone); 1770 dns_view_detach(&pview); 1771 if (zone != NULL) 1772 check_dbtype(&zone, empty_dbtypec, 1773 empty_dbtype, mctx); 1774 if (zone != NULL) { 1775 dns_zone_setview(zone, view); 1776 dns_zone_detach(&zone); 1777 continue; 1778 } 1779 } 1780 1781 CHECK(dns_zone_create(&zone, mctx)); 1782 CHECK(dns_zone_setorigin(zone, name)); 1783 dns_zone_setview(zone, view); 1784 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 1785 dns_zone_setclass(zone, view->rdclass); 1786 dns_zone_settype(zone, dns_zone_master); 1787 CHECK(dns_zone_setdbtype(zone, empty_dbtypec, 1788 empty_dbtype)); 1789 if (view->queryacl != NULL) 1790 dns_zone_setqueryacl(zone, view->queryacl); 1791 dns_zone_setdialup(zone, dns_dialuptype_no); 1792 dns_zone_setnotifytype(zone, dns_notifytype_no); 1793 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, 1794 ISC_TRUE); 1795 CHECK(dns_view_addzone(view, zone)); 1796 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 1797 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 1798 "automatic empty zone%s%s: %s", 1799 sep, viewname, empty); 1800 dns_zone_detach(&zone); 1801 } 1802 } 1803 1804 result = ISC_R_SUCCESS; 1805 1806 cleanup: 1807 if (zone != NULL) 1808 dns_zone_detach(&zone); 1809 if (dispatch4 != NULL) 1810 dns_dispatch_detach(&dispatch4); 1811 if (dispatch6 != NULL) 1812 dns_dispatch_detach(&dispatch6); 1813 if (order != NULL) 1814 dns_order_detach(&order); 1815 if (cmctx != NULL) 1816 isc_mem_detach(&cmctx); 1817 1818 if (cache != NULL) 1819 dns_cache_detach(&cache); 1820 1821 return (result); 1822} 1823 1824static isc_result_t 1825configure_hints(dns_view_t *view, const char *filename) { 1826 isc_result_t result; 1827 dns_db_t *db; 1828 1829 db = NULL; 1830 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db); 1831 if (result == ISC_R_SUCCESS) { 1832 dns_view_sethints(view, db); 1833 dns_db_detach(&db); 1834 } 1835 1836 return (result); 1837} 1838 1839static isc_result_t 1840configure_alternates(const cfg_obj_t *config, dns_view_t *view, 1841 const cfg_obj_t *alternates) 1842{ 1843 const cfg_obj_t *portobj; 1844 const cfg_obj_t *addresses; 1845 const cfg_listelt_t *element; 1846 isc_result_t result = ISC_R_SUCCESS; 1847 in_port_t port; 1848 1849 /* 1850 * Determine which port to send requests to. 1851 */ 1852 if (ns_g_lwresdonly && ns_g_port != 0) 1853 port = ns_g_port; 1854 else 1855 CHECKM(ns_config_getport(config, &port), "port"); 1856 1857 if (alternates != NULL) { 1858 portobj = cfg_tuple_get(alternates, "port"); 1859 if (cfg_obj_isuint32(portobj)) { 1860 isc_uint32_t val = cfg_obj_asuint32(portobj); 1861 if (val > ISC_UINT16_MAX) { 1862 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 1863 "port '%u' out of range", val); 1864 return (ISC_R_RANGE); 1865 } 1866 port = (in_port_t) val; 1867 } 1868 } 1869 1870 addresses = NULL; 1871 if (alternates != NULL) 1872 addresses = cfg_tuple_get(alternates, "addresses"); 1873 1874 for (element = cfg_list_first(addresses); 1875 element != NULL; 1876 element = cfg_list_next(element)) 1877 { 1878 const cfg_obj_t *alternate = cfg_listelt_value(element); 1879 isc_sockaddr_t sa; 1880 1881 if (!cfg_obj_issockaddr(alternate)) { 1882 dns_fixedname_t fixed; 1883 dns_name_t *name; 1884 const char *str = cfg_obj_asstring(cfg_tuple_get( 1885 alternate, "name")); 1886 isc_buffer_t buffer; 1887 in_port_t myport = port; 1888 1889 isc_buffer_init(&buffer, str, strlen(str)); 1890 isc_buffer_add(&buffer, strlen(str)); 1891 dns_fixedname_init(&fixed); 1892 name = dns_fixedname_name(&fixed); 1893 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 1894 ISC_FALSE, NULL)); 1895 1896 portobj = cfg_tuple_get(alternate, "port"); 1897 if (cfg_obj_isuint32(portobj)) { 1898 isc_uint32_t val = cfg_obj_asuint32(portobj); 1899 if (val > ISC_UINT16_MAX) { 1900 cfg_obj_log(portobj, ns_g_lctx, 1901 ISC_LOG_ERROR, 1902 "port '%u' out of range", 1903 val); 1904 return (ISC_R_RANGE); 1905 } 1906 myport = (in_port_t) val; 1907 } 1908 CHECK(dns_resolver_addalternate(view->resolver, NULL, 1909 name, myport)); 1910 continue; 1911 } 1912 1913 sa = *cfg_obj_assockaddr(alternate); 1914 if (isc_sockaddr_getport(&sa) == 0) 1915 isc_sockaddr_setport(&sa, port); 1916 CHECK(dns_resolver_addalternate(view->resolver, &sa, 1917 NULL, 0)); 1918 } 1919 1920 cleanup: 1921 return (result); 1922} 1923 1924static isc_result_t 1925configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin, 1926 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype) 1927{ 1928 const cfg_obj_t *portobj; 1929 const cfg_obj_t *faddresses; 1930 const cfg_listelt_t *element; 1931 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; 1932 isc_sockaddrlist_t addresses; 1933 isc_sockaddr_t *sa; 1934 isc_result_t result; 1935 in_port_t port; 1936 1937 /* 1938 * Determine which port to send forwarded requests to. 1939 */ 1940 if (ns_g_lwresdonly && ns_g_port != 0) 1941 port = ns_g_port; 1942 else 1943 CHECKM(ns_config_getport(config, &port), "port"); 1944 1945 if (forwarders != NULL) { 1946 portobj = cfg_tuple_get(forwarders, "port"); 1947 if (cfg_obj_isuint32(portobj)) { 1948 isc_uint32_t val = cfg_obj_asuint32(portobj); 1949 if (val > ISC_UINT16_MAX) { 1950 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 1951 "port '%u' out of range", val); 1952 return (ISC_R_RANGE); 1953 } 1954 port = (in_port_t) val; 1955 } 1956 } 1957 1958 faddresses = NULL; 1959 if (forwarders != NULL) 1960 faddresses = cfg_tuple_get(forwarders, "addresses"); 1961 1962 ISC_LIST_INIT(addresses); 1963 1964 for (element = cfg_list_first(faddresses); 1965 element != NULL; 1966 element = cfg_list_next(element)) 1967 { 1968 const cfg_obj_t *forwarder = cfg_listelt_value(element); 1969 sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t)); 1970 if (sa == NULL) { 1971 result = ISC_R_NOMEMORY; 1972 goto cleanup; 1973 } 1974 *sa = *cfg_obj_assockaddr(forwarder); 1975 if (isc_sockaddr_getport(sa) == 0) 1976 isc_sockaddr_setport(sa, port); 1977 ISC_LINK_INIT(sa, link); 1978 ISC_LIST_APPEND(addresses, sa, link); 1979 } 1980 1981 if (ISC_LIST_EMPTY(addresses)) { 1982 if (forwardtype != NULL) 1983 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 1984 "no forwarders seen; disabling " 1985 "forwarding"); 1986 fwdpolicy = dns_fwdpolicy_none; 1987 } else { 1988 if (forwardtype == NULL) 1989 fwdpolicy = dns_fwdpolicy_first; 1990 else { 1991 const char *forwardstr = cfg_obj_asstring(forwardtype); 1992 if (strcasecmp(forwardstr, "first") == 0) 1993 fwdpolicy = dns_fwdpolicy_first; 1994 else if (strcasecmp(forwardstr, "only") == 0) 1995 fwdpolicy = dns_fwdpolicy_only; 1996 else 1997 INSIST(0); 1998 } 1999 } 2000 2001 result = dns_fwdtable_add(view->fwdtable, origin, &addresses, 2002 fwdpolicy); 2003 if (result != ISC_R_SUCCESS) { 2004 char namebuf[DNS_NAME_FORMATSIZE]; 2005 dns_name_format(origin, namebuf, sizeof(namebuf)); 2006 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING, 2007 "could not set up forwarding for domain '%s': %s", 2008 namebuf, isc_result_totext(result)); 2009 goto cleanup; 2010 } 2011 2012 result = ISC_R_SUCCESS; 2013 2014 cleanup: 2015 2016 while (!ISC_LIST_EMPTY(addresses)) { 2017 sa = ISC_LIST_HEAD(addresses); 2018 ISC_LIST_UNLINK(addresses, sa, link); 2019 isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t)); 2020 } 2021 2022 return (result); 2023} 2024 2025/* 2026 * Create a new view and add it to the list. 2027 * 2028 * If 'vconfig' is NULL, create the default view. 2029 * 2030 * The view created is attached to '*viewp'. 2031 */ 2032static isc_result_t 2033create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist, 2034 dns_view_t **viewp) 2035{ 2036 isc_result_t result; 2037 const char *viewname; 2038 dns_rdataclass_t viewclass; 2039 dns_view_t *view = NULL; 2040 2041 if (vconfig != NULL) { 2042 const cfg_obj_t *classobj = NULL; 2043 2044 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); 2045 classobj = cfg_tuple_get(vconfig, "class"); 2046 result = ns_config_getclass(classobj, dns_rdataclass_in, 2047 &viewclass); 2048 } else { 2049 viewname = "_default"; 2050 viewclass = dns_rdataclass_in; 2051 } 2052 result = dns_viewlist_find(viewlist, viewname, viewclass, &view); 2053 if (result == ISC_R_SUCCESS) 2054 return (ISC_R_EXISTS); 2055 if (result != ISC_R_NOTFOUND) 2056 return (result); 2057 INSIST(view == NULL); 2058 2059 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view); 2060 if (result != ISC_R_SUCCESS) 2061 return (result); 2062 2063 ISC_LIST_APPEND(*viewlist, view, link); 2064 dns_view_attach(view, viewp); 2065 return (ISC_R_SUCCESS); 2066} 2067 2068/* 2069 * Configure or reconfigure a zone. 2070 */ 2071static isc_result_t 2072configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, 2073 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, 2074 cfg_aclconfctx_t *aclconf) 2075{ 2076 dns_view_t *pview = NULL; /* Production view */ 2077 dns_zone_t *zone = NULL; /* New or reused zone */ 2078 dns_zone_t *dupzone = NULL; 2079 const cfg_obj_t *options = NULL; 2080 const cfg_obj_t *zoptions = NULL; 2081 const cfg_obj_t *typeobj = NULL; 2082 const cfg_obj_t *forwarders = NULL; 2083 const cfg_obj_t *forwardtype = NULL; 2084 const cfg_obj_t *only = NULL; 2085 isc_result_t result; 2086 isc_result_t tresult; 2087 isc_buffer_t buffer; 2088 dns_fixedname_t fixorigin; 2089 dns_name_t *origin; 2090 const char *zname; 2091 dns_rdataclass_t zclass; 2092 const char *ztypestr; 2093 2094 options = NULL; 2095 (void)cfg_map_get(config, "options", &options); 2096 2097 zoptions = cfg_tuple_get(zconfig, "options"); 2098 2099 /* 2100 * Get the zone origin as a dns_name_t. 2101 */ 2102 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); 2103 isc_buffer_init(&buffer, zname, strlen(zname)); 2104 isc_buffer_add(&buffer, strlen(zname)); 2105 dns_fixedname_init(&fixorigin); 2106 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), 2107 &buffer, dns_rootname, ISC_FALSE, NULL)); 2108 origin = dns_fixedname_name(&fixorigin); 2109 2110 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"), 2111 view->rdclass, &zclass)); 2112 if (zclass != view->rdclass) { 2113 const char *vname = NULL; 2114 if (vconfig != NULL) 2115 vname = cfg_obj_asstring(cfg_tuple_get(vconfig, 2116 "name")); 2117 else 2118 vname = "<default view>"; 2119 2120 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2121 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 2122 "zone '%s': wrong class for view '%s'", 2123 zname, vname); 2124 result = ISC_R_FAILURE; 2125 goto cleanup; 2126 } 2127 2128 (void)cfg_map_get(zoptions, "type", &typeobj); 2129 if (typeobj == NULL) { 2130 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 2131 "zone '%s' 'type' not specified", zname); 2132 return (ISC_R_FAILURE); 2133 } 2134 ztypestr = cfg_obj_asstring(typeobj); 2135 2136 /* 2137 * "hints zones" aren't zones. If we've got one, 2138 * configure it and return. 2139 */ 2140 if (strcasecmp(ztypestr, "hint") == 0) { 2141 const cfg_obj_t *fileobj = NULL; 2142 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) { 2143 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2144 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 2145 "zone '%s': 'file' not specified", 2146 zname); 2147 result = ISC_R_FAILURE; 2148 goto cleanup; 2149 } 2150 if (dns_name_equal(origin, dns_rootname)) { 2151 const char *hintsfile = cfg_obj_asstring(fileobj); 2152 2153 result = configure_hints(view, hintsfile); 2154 if (result != ISC_R_SUCCESS) { 2155 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2156 NS_LOGMODULE_SERVER, 2157 ISC_LOG_ERROR, 2158 "could not configure root hints " 2159 "from '%s': %s", hintsfile, 2160 isc_result_totext(result)); 2161 goto cleanup; 2162 } 2163 /* 2164 * Hint zones may also refer to delegation only points. 2165 */ 2166 only = NULL; 2167 tresult = cfg_map_get(zoptions, "delegation-only", 2168 &only); 2169 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only)) 2170 CHECK(dns_view_adddelegationonly(view, origin)); 2171 } else { 2172 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2173 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 2174 "ignoring non-root hint zone '%s'", 2175 zname); 2176 result = ISC_R_SUCCESS; 2177 } 2178 /* Skip ordinary zone processing. */ 2179 goto cleanup; 2180 } 2181 2182 /* 2183 * "forward zones" aren't zones either. Translate this syntax into 2184 * the appropriate selective forwarding configuration and return. 2185 */ 2186 if (strcasecmp(ztypestr, "forward") == 0) { 2187 forwardtype = NULL; 2188 forwarders = NULL; 2189 2190 (void)cfg_map_get(zoptions, "forward", &forwardtype); 2191 (void)cfg_map_get(zoptions, "forwarders", &forwarders); 2192 result = configure_forward(config, view, origin, forwarders, 2193 forwardtype); 2194 goto cleanup; 2195 } 2196 2197 /* 2198 * "delegation-only zones" aren't zones either. 2199 */ 2200 if (strcasecmp(ztypestr, "delegation-only") == 0) { 2201 result = dns_view_adddelegationonly(view, origin); 2202 goto cleanup; 2203 } 2204 2205 /* 2206 * Check for duplicates in the new zone table. 2207 */ 2208 result = dns_view_findzone(view, origin, &dupzone); 2209 if (result == ISC_R_SUCCESS) { 2210 /* 2211 * We already have this zone! 2212 */ 2213 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, 2214 "zone '%s' already exists", zname); 2215 dns_zone_detach(&dupzone); 2216 result = ISC_R_EXISTS; 2217 goto cleanup; 2218 } 2219 INSIST(dupzone == NULL); 2220 2221 /* 2222 * See if we can reuse an existing zone. This is 2223 * only possible if all of these are true: 2224 * - The zone's view exists 2225 * - A zone with the right name exists in the view 2226 * - The zone is compatible with the config 2227 * options (e.g., an existing master zone cannot 2228 * be reused if the options specify a slave zone) 2229 */ 2230 result = dns_viewlist_find(&ns_g_server->viewlist, 2231 view->name, view->rdclass, 2232 &pview); 2233 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 2234 goto cleanup; 2235 if (pview != NULL) 2236 result = dns_view_findzone(pview, origin, &zone); 2237 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) 2238 goto cleanup; 2239 if (zone != NULL && !ns_zone_reusable(zone, zconfig)) 2240 dns_zone_detach(&zone); 2241 2242 if (zone != NULL) { 2243 /* 2244 * We found a reusable zone. Make it use the 2245 * new view. 2246 */ 2247 dns_zone_setview(zone, view); 2248 if (view->acache != NULL) 2249 dns_zone_setacache(zone, view->acache); 2250 } else { 2251 /* 2252 * We cannot reuse an existing zone, we have 2253 * to create a new one. 2254 */ 2255 CHECK(dns_zone_create(&zone, mctx)); 2256 CHECK(dns_zone_setorigin(zone, origin)); 2257 dns_zone_setview(zone, view); 2258 if (view->acache != NULL) 2259 dns_zone_setacache(zone, view->acache); 2260 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone)); 2261 } 2262 2263 /* 2264 * If the zone contains a 'forwarders' statement, configure 2265 * selective forwarding. 2266 */ 2267 forwarders = NULL; 2268 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) 2269 { 2270 forwardtype = NULL; 2271 (void)cfg_map_get(zoptions, "forward", &forwardtype); 2272 CHECK(configure_forward(config, view, origin, forwarders, 2273 forwardtype)); 2274 } 2275 2276 /* 2277 * Stub and forward zones may also refer to delegation only points. 2278 */ 2279 only = NULL; 2280 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) 2281 { 2282 if (cfg_obj_asboolean(only)) 2283 CHECK(dns_view_adddelegationonly(view, origin)); 2284 } 2285 2286 /* 2287 * Configure the zone. 2288 */ 2289 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); 2290 2291 /* 2292 * Add the zone to its view in the new view list. 2293 */ 2294 CHECK(dns_view_addzone(view, zone)); 2295 2296 cleanup: 2297 if (zone != NULL) 2298 dns_zone_detach(&zone); 2299 if (pview != NULL) 2300 dns_view_detach(&pview); 2301 2302 return (result); 2303} 2304 2305/* 2306 * Configure a single server quota. 2307 */ 2308static void 2309configure_server_quota(const cfg_obj_t **maps, const char *name, 2310 isc_quota_t *quota) 2311{ 2312 const cfg_obj_t *obj = NULL; 2313 isc_result_t result; 2314 2315 result = ns_config_get(maps, name, &obj); 2316 INSIST(result == ISC_R_SUCCESS); 2317 isc_quota_max(quota, cfg_obj_asuint32(obj)); 2318} 2319 2320/* 2321 * This function is called as soon as the 'directory' statement has been 2322 * parsed. This can be extended to support other options if necessary. 2323 */ 2324static isc_result_t 2325directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { 2326 isc_result_t result; 2327 const char *directory; 2328 2329 REQUIRE(strcasecmp("directory", clausename) == 0); 2330 2331 UNUSED(arg); 2332 UNUSED(clausename); 2333 2334 /* 2335 * Change directory. 2336 */ 2337 directory = cfg_obj_asstring(obj); 2338 2339 if (! isc_file_ischdiridempotent(directory)) 2340 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING, 2341 "option 'directory' contains relative path '%s'", 2342 directory); 2343 2344 result = isc_dir_chdir(directory); 2345 if (result != ISC_R_SUCCESS) { 2346 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, 2347 "change directory to '%s' failed: %s", 2348 directory, isc_result_totext(result)); 2349 return (result); 2350 } 2351 2352 return (ISC_R_SUCCESS); 2353} 2354 2355static void 2356scan_interfaces(ns_server_t *server, isc_boolean_t verbose) { 2357 isc_boolean_t match_mapped = server->aclenv.match_mapped; 2358 2359 ns_interfacemgr_scan(server->interfacemgr, verbose); 2360 /* 2361 * Update the "localhost" and "localnets" ACLs to match the 2362 * current set of network interfaces. 2363 */ 2364 dns_aclenv_copy(&server->aclenv, 2365 ns_interfacemgr_getaclenv(server->interfacemgr)); 2366 2367 server->aclenv.match_mapped = match_mapped; 2368} 2369 2370static isc_result_t 2371add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr) { 2372 ns_listenelt_t *lelt = NULL; 2373 dns_acl_t *src_acl = NULL; 2374 dns_aclelement_t aelt; 2375 isc_result_t result; 2376 isc_sockaddr_t any_sa6; 2377 2378 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6); 2379 2380 isc_sockaddr_any6(&any_sa6); 2381 if (!isc_sockaddr_equal(&any_sa6, addr)) { 2382 aelt.type = dns_aclelementtype_ipprefix; 2383 aelt.negative = ISC_FALSE; 2384 aelt.u.ip_prefix.prefixlen = 128; 2385 isc_netaddr_fromin6(&aelt.u.ip_prefix.address, 2386 &addr->type.sin6.sin6_addr); 2387 2388 result = dns_acl_create(mctx, 1, &src_acl); 2389 if (result != ISC_R_SUCCESS) 2390 return (result); 2391 result = dns_acl_appendelement(src_acl, &aelt); 2392 if (result != ISC_R_SUCCESS) 2393 goto clean; 2394 2395 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), 2396 src_acl, &lelt); 2397 if (result != ISC_R_SUCCESS) 2398 goto clean; 2399 ISC_LIST_APPEND(list->elts, lelt, link); 2400 } 2401 2402 return (ISC_R_SUCCESS); 2403 2404 clean: 2405 INSIST(lelt == NULL); 2406 dns_acl_detach(&src_acl); 2407 2408 return (result); 2409} 2410 2411/* 2412 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust() 2413 * to update the listening interfaces accordingly. 2414 * We currently only consider IPv6, because this only affects IPv6 wildcard 2415 * sockets. 2416 */ 2417static void 2418adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) { 2419 isc_result_t result; 2420 ns_listenlist_t *list = NULL; 2421 dns_view_t *view; 2422 dns_zone_t *zone, *next; 2423 isc_sockaddr_t addr, *addrp; 2424 2425 result = ns_listenlist_create(mctx, &list); 2426 if (result != ISC_R_SUCCESS) 2427 return; 2428 2429 for (view = ISC_LIST_HEAD(server->viewlist); 2430 view != NULL; 2431 view = ISC_LIST_NEXT(view, link)) { 2432 dns_dispatch_t *dispatch6; 2433 2434 dispatch6 = dns_resolver_dispatchv6(view->resolver); 2435 if (dispatch6 == NULL) 2436 continue; 2437 result = dns_dispatch_getlocaladdress(dispatch6, &addr); 2438 if (result != ISC_R_SUCCESS) 2439 goto fail; 2440 result = add_listenelt(mctx, list, &addr); 2441 if (result != ISC_R_SUCCESS) 2442 goto fail; 2443 } 2444 2445 zone = NULL; 2446 for (result = dns_zone_first(server->zonemgr, &zone); 2447 result == ISC_R_SUCCESS; 2448 next = NULL, result = dns_zone_next(zone, &next), zone = next) { 2449 dns_view_t *zoneview; 2450 2451 /* 2452 * At this point the zone list may contain a stale zone 2453 * just removed from the configuration. To see the validity, 2454 * check if the corresponding view is in our current view list. 2455 * There may also be old zones that are still in the process 2456 * of shutting down and have detached from their old view 2457 * (zoneview == NULL). 2458 */ 2459 zoneview = dns_zone_getview(zone); 2460 if (zoneview == NULL) 2461 continue; 2462 for (view = ISC_LIST_HEAD(server->viewlist); 2463 view != NULL && view != zoneview; 2464 view = ISC_LIST_NEXT(view, link)) 2465 ; 2466 if (view == NULL) 2467 continue; 2468 2469 addrp = dns_zone_getnotifysrc6(zone); 2470 result = add_listenelt(mctx, list, addrp); 2471 if (result != ISC_R_SUCCESS) 2472 goto fail; 2473 2474 addrp = dns_zone_getxfrsource6(zone); 2475 result = add_listenelt(mctx, list, addrp); 2476 if (result != ISC_R_SUCCESS) 2477 goto fail; 2478 } 2479 2480 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE); 2481 2482 clean: 2483 ns_listenlist_detach(&list); 2484 return; 2485 2486 fail: 2487 /* 2488 * Even when we failed the procedure, most of other interfaces 2489 * should work correctly. We therefore just warn it. 2490 */ 2491 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 2492 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 2493 "could not adjust the listen-on list; " 2494 "some interfaces may not work"); 2495 goto clean; 2496} 2497 2498/* 2499 * This event callback is invoked to do periodic network 2500 * interface scanning. 2501 */ 2502static void 2503interface_timer_tick(isc_task_t *task, isc_event_t *event) { 2504 isc_result_t result; 2505 ns_server_t *server = (ns_server_t *) event->ev_arg; 2506 INSIST(task == server->task); 2507 UNUSED(task); 2508 isc_event_free(&event); 2509 /* 2510 * XXX should scan interfaces unlocked and get exclusive access 2511 * only to replace ACLs. 2512 */ 2513 result = isc_task_beginexclusive(server->task); 2514 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2515 scan_interfaces(server, ISC_FALSE); 2516 isc_task_endexclusive(server->task); 2517} 2518 2519static void 2520heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) { 2521 ns_server_t *server = (ns_server_t *) event->ev_arg; 2522 dns_view_t *view; 2523 2524 UNUSED(task); 2525 isc_event_free(&event); 2526 view = ISC_LIST_HEAD(server->viewlist); 2527 while (view != NULL) { 2528 dns_view_dialup(view); 2529 view = ISC_LIST_NEXT(view, link); 2530 } 2531} 2532 2533static void 2534pps_timer_tick(isc_task_t *task, isc_event_t *event) { 2535 static unsigned int oldrequests = 0; 2536 unsigned int requests = ns_client_requests; 2537 2538 UNUSED(task); 2539 isc_event_free(&event); 2540 2541 /* 2542 * Don't worry about wrapping as the overflow result will be right. 2543 */ 2544 dns_pps = (requests - oldrequests) / 1200; 2545 oldrequests = requests; 2546} 2547 2548/* 2549 * Replace the current value of '*field', a dynamically allocated 2550 * string or NULL, with a dynamically allocated copy of the 2551 * null-terminated string pointed to by 'value', or NULL. 2552 */ 2553static isc_result_t 2554setstring(ns_server_t *server, char **field, const char *value) { 2555 char *copy; 2556 2557 if (value != NULL) { 2558 copy = isc_mem_strdup(server->mctx, value); 2559 if (copy == NULL) 2560 return (ISC_R_NOMEMORY); 2561 } else { 2562 copy = NULL; 2563 } 2564 2565 if (*field != NULL) 2566 isc_mem_free(server->mctx, *field); 2567 2568 *field = copy; 2569 return (ISC_R_SUCCESS); 2570} 2571 2572/* 2573 * Replace the current value of '*field', a dynamically allocated 2574 * string or NULL, with another dynamically allocated string 2575 * or NULL if whether 'obj' is a string or void value, respectively. 2576 */ 2577static isc_result_t 2578setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) { 2579 if (cfg_obj_isvoid(obj)) 2580 return (setstring(server, field, NULL)); 2581 else 2582 return (setstring(server, field, cfg_obj_asstring(obj))); 2583} 2584 2585static void 2586set_limit(const cfg_obj_t **maps, const char *configname, 2587 const char *description, isc_resource_t resourceid, 2588 isc_resourcevalue_t defaultvalue) 2589{ 2590 const cfg_obj_t *obj = NULL; 2591 const char *resource; 2592 isc_resourcevalue_t value; 2593 isc_result_t result; 2594 2595 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS) 2596 return; 2597 2598 if (cfg_obj_isstring(obj)) { 2599 resource = cfg_obj_asstring(obj); 2600 if (strcasecmp(resource, "unlimited") == 0) 2601 value = ISC_RESOURCE_UNLIMITED; 2602 else { 2603 INSIST(strcasecmp(resource, "default") == 0); 2604 value = defaultvalue; 2605 } 2606 } else 2607 value = cfg_obj_asuint64(obj); 2608 2609 result = isc_resource_setlimit(resourceid, value); 2610 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2611 result == ISC_R_SUCCESS ? 2612 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING, 2613 "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s", 2614 description, value, isc_result_totext(result)); 2615} 2616 2617#define SETLIMIT(cfgvar, resource, description) \ 2618 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \ 2619 ns_g_init ## resource) 2620 2621static void 2622set_limits(const cfg_obj_t **maps) { 2623 SETLIMIT("stacksize", stacksize, "stack size"); 2624 SETLIMIT("datasize", datasize, "data size"); 2625 SETLIMIT("coresize", coresize, "core size"); 2626 SETLIMIT("files", openfiles, "open files"); 2627} 2628 2629static isc_result_t 2630portlist_fromconf(dns_portlist_t *portlist, unsigned int family, 2631 const cfg_obj_t *ports) 2632{ 2633 const cfg_listelt_t *element; 2634 isc_result_t result = ISC_R_SUCCESS; 2635 2636 for (element = cfg_list_first(ports); 2637 element != NULL; 2638 element = cfg_list_next(element)) { 2639 const cfg_obj_t *obj = cfg_listelt_value(element); 2640 in_port_t port = (in_port_t)cfg_obj_asuint32(obj); 2641 2642 result = dns_portlist_add(portlist, family, port); 2643 if (result != ISC_R_SUCCESS) 2644 break; 2645 } 2646 return (result); 2647} 2648 2649static isc_result_t 2650removed(dns_zone_t *zone, void *uap) { 2651 const char *type; 2652 2653 if (dns_zone_getview(zone) != uap) 2654 return (ISC_R_SUCCESS); 2655 2656 switch (dns_zone_gettype(zone)) { 2657 case dns_zone_master: 2658 type = "master"; 2659 break; 2660 case dns_zone_slave: 2661 type = "slave"; 2662 break; 2663 case dns_zone_stub: 2664 type = "stub"; 2665 break; 2666 default: 2667 type = "other"; 2668 break; 2669 } 2670 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type); 2671 return (ISC_R_SUCCESS); 2672} 2673 2674static isc_result_t 2675load_configuration(const char *filename, ns_server_t *server, 2676 isc_boolean_t first_time) 2677{ 2678 isc_result_t result; 2679 isc_interval_t interval; 2680 cfg_parser_t *parser = NULL; 2681 cfg_obj_t *config; 2682 const cfg_obj_t *options; 2683 const cfg_obj_t *views; 2684 const cfg_obj_t *obj; 2685 const cfg_obj_t *v4ports, *v6ports; 2686 const cfg_obj_t *maps[3]; 2687 const cfg_obj_t *builtin_views; 2688 const cfg_listelt_t *element; 2689 dns_view_t *view = NULL; 2690 dns_view_t *view_next; 2691 dns_viewlist_t viewlist; 2692 dns_viewlist_t tmpviewlist; 2693 cfg_aclconfctx_t aclconfctx; 2694 isc_uint32_t interface_interval; 2695 isc_uint32_t heartbeat_interval; 2696 isc_uint32_t udpsize; 2697 in_port_t listen_port; 2698 int i; 2699 2700 cfg_aclconfctx_init(&aclconfctx); 2701 ISC_LIST_INIT(viewlist); 2702 2703 /* Ensure exclusive access to configuration data. */ 2704 result = isc_task_beginexclusive(server->task); 2705 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2706 2707 /* 2708 * Parse the global default pseudo-config file. 2709 */ 2710 if (first_time) { 2711 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config)); 2712 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options", 2713 &ns_g_defaults) == 2714 ISC_R_SUCCESS); 2715 } 2716 2717 /* 2718 * Parse the configuration file using the new config code. 2719 */ 2720 result = ISC_R_FAILURE; 2721 config = NULL; 2722 2723 /* 2724 * Unless this is lwresd with the -C option, parse the config file. 2725 */ 2726 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) { 2727 isc_log_write(ns_g_lctx, 2728 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2729 ISC_LOG_INFO, "loading configuration from '%s'", 2730 filename); 2731 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); 2732 cfg_parser_setcallback(parser, directory_callback, NULL); 2733 result = cfg_parse_file(parser, filename, &cfg_type_namedconf, 2734 &config); 2735 } 2736 2737 /* 2738 * If this is lwresd with the -C option, or lwresd with no -C or -c 2739 * option where the above parsing failed, parse resolv.conf. 2740 */ 2741 if (ns_g_lwresdonly && 2742 (lwresd_g_useresolvconf || 2743 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND))) 2744 { 2745 isc_log_write(ns_g_lctx, 2746 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 2747 ISC_LOG_INFO, "loading configuration from '%s'", 2748 lwresd_g_resolvconffile); 2749 if (parser != NULL) 2750 cfg_parser_destroy(&parser); 2751 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser)); 2752 result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser, 2753 &config); 2754 } 2755 CHECK(result); 2756 2757 /* 2758 * Check the validity of the configuration. 2759 */ 2760 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx)); 2761 2762 /* 2763 * Fill in the maps array, used for resolving defaults. 2764 */ 2765 i = 0; 2766 options = NULL; 2767 result = cfg_map_get(config, "options", &options); 2768 if (result == ISC_R_SUCCESS) 2769 maps[i++] = options; 2770 maps[i++] = ns_g_defaults; 2771 maps[i++] = NULL; 2772 2773 /* 2774 * Set process limits, which (usually) needs to be done as root. 2775 */ 2776 set_limits(maps); 2777 2778 /* 2779 * Configure various server options. 2780 */ 2781 configure_server_quota(maps, "transfers-out", &server->xfroutquota); 2782 configure_server_quota(maps, "tcp-clients", &server->tcpquota); 2783 configure_server_quota(maps, "recursive-clients", 2784 &server->recursionquota); 2785 if (server->recursionquota.max > 1000) 2786 isc_quota_soft(&server->recursionquota, 2787 server->recursionquota.max - 100); 2788 else 2789 isc_quota_soft(&server->recursionquota, 0); 2790 2791 CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx, 2792 ns_g_mctx, &server->blackholeacl)); 2793 if (server->blackholeacl != NULL) 2794 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr, 2795 server->blackholeacl); 2796 2797 obj = NULL; 2798 result = ns_config_get(maps, "match-mapped-addresses", &obj); 2799 INSIST(result == ISC_R_SUCCESS); 2800 server->aclenv.match_mapped = cfg_obj_asboolean(obj); 2801 2802 v4ports = NULL; 2803 v6ports = NULL; 2804 (void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports); 2805 (void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports); 2806 if (v4ports != NULL || v6ports != NULL) { 2807 dns_portlist_t *portlist = NULL; 2808 result = dns_portlist_create(ns_g_mctx, &portlist); 2809 if (result == ISC_R_SUCCESS && v4ports != NULL) 2810 result = portlist_fromconf(portlist, AF_INET, v4ports); 2811 if (result == ISC_R_SUCCESS && v6ports != NULL) 2812 portlist_fromconf(portlist, AF_INET6, v6ports); 2813 if (result == ISC_R_SUCCESS) 2814 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist); 2815 if (portlist != NULL) 2816 dns_portlist_detach(&portlist); 2817 CHECK(result); 2818 } else 2819 dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL); 2820 2821 /* 2822 * Set the EDNS UDP size when we don't match a view. 2823 */ 2824 obj = NULL; 2825 result = ns_config_get(maps, "edns-udp-size", &obj); 2826 INSIST(result == ISC_R_SUCCESS); 2827 udpsize = cfg_obj_asuint32(obj); 2828 if (udpsize < 512) 2829 udpsize = 512; 2830 if (udpsize > 4096) 2831 udpsize = 4096; 2832 ns_g_udpsize = (isc_uint16_t)udpsize; 2833 2834 /* 2835 * Configure the zone manager. 2836 */ 2837 obj = NULL; 2838 result = ns_config_get(maps, "transfers-in", &obj); 2839 INSIST(result == ISC_R_SUCCESS); 2840 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj)); 2841 2842 obj = NULL; 2843 result = ns_config_get(maps, "transfers-per-ns", &obj); 2844 INSIST(result == ISC_R_SUCCESS); 2845 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj)); 2846 2847 obj = NULL; 2848 result = ns_config_get(maps, "serial-query-rate", &obj); 2849 INSIST(result == ISC_R_SUCCESS); 2850 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj)); 2851 2852 /* 2853 * Determine which port to use for listening for incoming connections. 2854 */ 2855 if (ns_g_port != 0) 2856 listen_port = ns_g_port; 2857 else 2858 CHECKM(ns_config_getport(config, &listen_port), "port"); 2859 2860 /* 2861 * Find the listen queue depth. 2862 */ 2863 obj = NULL; 2864 result = ns_config_get(maps, "tcp-listen-queue", &obj); 2865 INSIST(result == ISC_R_SUCCESS); 2866 ns_g_listen = cfg_obj_asuint32(obj); 2867 if (ns_g_listen < 3) 2868 ns_g_listen = 3; 2869 2870 /* 2871 * Configure the interface manager according to the "listen-on" 2872 * statement. 2873 */ 2874 { 2875 const cfg_obj_t *clistenon = NULL; 2876 ns_listenlist_t *listenon = NULL; 2877 2878 clistenon = NULL; 2879 /* 2880 * Even though listen-on is present in the default 2881 * configuration, we can't use it here, since it isn't 2882 * used if we're in lwresd mode. This way is easier. 2883 */ 2884 if (options != NULL) 2885 (void)cfg_map_get(options, "listen-on", &clistenon); 2886 if (clistenon != NULL) { 2887 result = ns_listenlist_fromconfig(clistenon, 2888 config, 2889 &aclconfctx, 2890 ns_g_mctx, 2891 &listenon); 2892 } else if (!ns_g_lwresdonly) { 2893 /* 2894 * Not specified, use default. 2895 */ 2896 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 2897 ISC_TRUE, &listenon)); 2898 } 2899 if (listenon != NULL) { 2900 ns_interfacemgr_setlistenon4(server->interfacemgr, 2901 listenon); 2902 ns_listenlist_detach(&listenon); 2903 } 2904 } 2905 /* 2906 * Ditto for IPv6. 2907 */ 2908 { 2909 const cfg_obj_t *clistenon = NULL; 2910 ns_listenlist_t *listenon = NULL; 2911 2912 if (options != NULL) 2913 (void)cfg_map_get(options, "listen-on-v6", &clistenon); 2914 if (clistenon != NULL) { 2915 result = ns_listenlist_fromconfig(clistenon, 2916 config, 2917 &aclconfctx, 2918 ns_g_mctx, 2919 &listenon); 2920 } else if (!ns_g_lwresdonly) { 2921 /* 2922 * Not specified, use default. 2923 */ 2924 CHECK(ns_listenlist_default(ns_g_mctx, listen_port, 2925 ISC_FALSE, &listenon)); 2926 } 2927 if (listenon != NULL) { 2928 ns_interfacemgr_setlistenon6(server->interfacemgr, 2929 listenon); 2930 ns_listenlist_detach(&listenon); 2931 } 2932 } 2933 2934 /* 2935 * Rescan the interface list to pick up changes in the 2936 * listen-on option. It's important that we do this before we try 2937 * to configure the query source, since the dispatcher we use might 2938 * be shared with an interface. 2939 */ 2940 scan_interfaces(server, ISC_TRUE); 2941 2942 /* 2943 * Arrange for further interface scanning to occur periodically 2944 * as specified by the "interface-interval" option. 2945 */ 2946 obj = NULL; 2947 result = ns_config_get(maps, "interface-interval", &obj); 2948 INSIST(result == ISC_R_SUCCESS); 2949 interface_interval = cfg_obj_asuint32(obj) * 60; 2950 if (interface_interval == 0) { 2951 CHECK(isc_timer_reset(server->interface_timer, 2952 isc_timertype_inactive, 2953 NULL, NULL, ISC_TRUE)); 2954 } else if (server->interface_interval != interface_interval) { 2955 isc_interval_set(&interval, interface_interval, 0); 2956 CHECK(isc_timer_reset(server->interface_timer, 2957 isc_timertype_ticker, 2958 NULL, &interval, ISC_FALSE)); 2959 } 2960 server->interface_interval = interface_interval; 2961 2962 /* 2963 * Configure the dialup heartbeat timer. 2964 */ 2965 obj = NULL; 2966 result = ns_config_get(maps, "heartbeat-interval", &obj); 2967 INSIST(result == ISC_R_SUCCESS); 2968 heartbeat_interval = cfg_obj_asuint32(obj) * 60; 2969 if (heartbeat_interval == 0) { 2970 CHECK(isc_timer_reset(server->heartbeat_timer, 2971 isc_timertype_inactive, 2972 NULL, NULL, ISC_TRUE)); 2973 } else if (server->heartbeat_interval != heartbeat_interval) { 2974 isc_interval_set(&interval, heartbeat_interval, 0); 2975 CHECK(isc_timer_reset(server->heartbeat_timer, 2976 isc_timertype_ticker, 2977 NULL, &interval, ISC_FALSE)); 2978 } 2979 server->heartbeat_interval = heartbeat_interval; 2980 2981 isc_interval_set(&interval, 1200, 0); 2982 CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL, 2983 &interval, ISC_FALSE)); 2984 2985 /* 2986 * Configure and freeze all explicit views. Explicit 2987 * views that have zones were already created at parsing 2988 * time, but views with no zones must be created here. 2989 */ 2990 views = NULL; 2991 (void)cfg_map_get(config, "view", &views); 2992 for (element = cfg_list_first(views); 2993 element != NULL; 2994 element = cfg_list_next(element)) 2995 { 2996 const cfg_obj_t *vconfig = cfg_listelt_value(element); 2997 view = NULL; 2998 2999 CHECK(create_view(vconfig, &viewlist, &view)); 3000 INSIST(view != NULL); 3001 CHECK(configure_view(view, config, vconfig, 3002 ns_g_mctx, &aclconfctx, ISC_TRUE)); 3003 dns_view_freeze(view); 3004 dns_view_detach(&view); 3005 } 3006 3007 /* 3008 * Make sure we have a default view if and only if there 3009 * were no explicit views. 3010 */ 3011 if (views == NULL) { 3012 /* 3013 * No explicit views; there ought to be a default view. 3014 * There may already be one created as a side effect 3015 * of zone statements, or we may have to create one. 3016 * In either case, we need to configure and freeze it. 3017 */ 3018 CHECK(create_view(NULL, &viewlist, &view)); 3019 CHECK(configure_view(view, config, NULL, ns_g_mctx, 3020 &aclconfctx, ISC_TRUE)); 3021 dns_view_freeze(view); 3022 dns_view_detach(&view); 3023 } 3024 3025 /* 3026 * Create (or recreate) the built-in views. Currently 3027 * there is only one, the _bind view. 3028 */ 3029 builtin_views = NULL; 3030 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view", 3031 &builtin_views) == ISC_R_SUCCESS); 3032 for (element = cfg_list_first(builtin_views); 3033 element != NULL; 3034 element = cfg_list_next(element)) 3035 { 3036 const cfg_obj_t *vconfig = cfg_listelt_value(element); 3037 CHECK(create_view(vconfig, &viewlist, &view)); 3038 CHECK(configure_view(view, config, vconfig, ns_g_mctx, 3039 &aclconfctx, ISC_FALSE)); 3040 dns_view_freeze(view); 3041 dns_view_detach(&view); 3042 view = NULL; 3043 } 3044 3045 /* 3046 * Swap our new view list with the production one. 3047 */ 3048 tmpviewlist = server->viewlist; 3049 server->viewlist = viewlist; 3050 viewlist = tmpviewlist; 3051 3052 /* 3053 * Load the TKEY information from the configuration. 3054 */ 3055 if (options != NULL) { 3056 dns_tkeyctx_t *t = NULL; 3057 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy, 3058 &t), 3059 "configuring TKEY"); 3060 if (server->tkeyctx != NULL) 3061 dns_tkeyctx_destroy(&server->tkeyctx); 3062 server->tkeyctx = t; 3063 } 3064 3065 /* 3066 * Bind the control port(s). 3067 */ 3068 CHECKM(ns_controls_configure(ns_g_server->controls, config, 3069 &aclconfctx), 3070 "binding control channel(s)"); 3071 3072 /* 3073 * Bind the lwresd port(s). 3074 */ 3075 CHECKM(ns_lwresd_configure(ns_g_mctx, config), 3076 "binding lightweight resolver ports"); 3077 3078 /* 3079 * Open the source of entropy. 3080 */ 3081 if (first_time) { 3082 obj = NULL; 3083 result = ns_config_get(maps, "random-device", &obj); 3084 if (result != ISC_R_SUCCESS) { 3085 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3086 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3087 "no source of entropy found"); 3088 } else { 3089 const char *randomdev = cfg_obj_asstring(obj); 3090 result = isc_entropy_createfilesource(ns_g_entropy, 3091 randomdev); 3092 if (result != ISC_R_SUCCESS) 3093 isc_log_write(ns_g_lctx, 3094 NS_LOGCATEGORY_GENERAL, 3095 NS_LOGMODULE_SERVER, 3096 ISC_LOG_INFO, 3097 "could not open entropy source " 3098 "%s: %s", 3099 randomdev, 3100 isc_result_totext(result)); 3101#ifdef PATH_RANDOMDEV 3102 if (ns_g_fallbackentropy != NULL) { 3103 if (result != ISC_R_SUCCESS) { 3104 isc_log_write(ns_g_lctx, 3105 NS_LOGCATEGORY_GENERAL, 3106 NS_LOGMODULE_SERVER, 3107 ISC_LOG_INFO, 3108 "using pre-chroot entropy source " 3109 "%s", 3110 PATH_RANDOMDEV); 3111 isc_entropy_detach(&ns_g_entropy); 3112 isc_entropy_attach(ns_g_fallbackentropy, 3113 &ns_g_entropy); 3114 } 3115 isc_entropy_detach(&ns_g_fallbackentropy); 3116 } 3117#endif 3118 } 3119 } 3120 3121 /* 3122 * Relinquish root privileges. 3123 */ 3124 if (first_time) 3125 ns_os_changeuser(); 3126 3127 /* 3128 * Configure the logging system. 3129 * 3130 * Do this after changing UID to make sure that any log 3131 * files specified in named.conf get created by the 3132 * unprivileged user, not root. 3133 */ 3134 if (ns_g_logstderr) { 3135 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3136 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 3137 "ignoring config file logging " 3138 "statement due to -g option"); 3139 } else { 3140 const cfg_obj_t *logobj = NULL; 3141 isc_logconfig_t *logc = NULL; 3142 3143 CHECKM(isc_logconfig_create(ns_g_lctx, &logc), 3144 "creating new logging configuration"); 3145 3146 logobj = NULL; 3147 (void)cfg_map_get(config, "logging", &logobj); 3148 if (logobj != NULL) { 3149 CHECKM(ns_log_configure(logc, logobj), 3150 "configuring logging"); 3151 } else { 3152 CHECKM(ns_log_setdefaultchannels(logc), 3153 "setting up default logging channels"); 3154 CHECKM(ns_log_setunmatchedcategory(logc), 3155 "setting up default 'category unmatched'"); 3156 CHECKM(ns_log_setdefaultcategory(logc), 3157 "setting up default 'category default'"); 3158 } 3159 3160 result = isc_logconfig_use(ns_g_lctx, logc); 3161 if (result != ISC_R_SUCCESS) { 3162 isc_logconfig_destroy(&logc); 3163 CHECKM(result, "installing logging configuration"); 3164 } 3165 3166 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3167 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), 3168 "now using logging configuration from " 3169 "config file"); 3170 } 3171 3172 /* 3173 * Set the default value of the query logging flag depending 3174 * whether a "queries" category has been defined. This is 3175 * a disgusting hack, but we need to do this for BIND 8 3176 * compatibility. 3177 */ 3178 if (first_time) { 3179 const cfg_obj_t *logobj = NULL; 3180 const cfg_obj_t *categories = NULL; 3181 3182 obj = NULL; 3183 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) { 3184 server->log_queries = cfg_obj_asboolean(obj); 3185 } else { 3186 3187 (void)cfg_map_get(config, "logging", &logobj); 3188 if (logobj != NULL) 3189 (void)cfg_map_get(logobj, "category", 3190 &categories); 3191 if (categories != NULL) { 3192 const cfg_listelt_t *element; 3193 for (element = cfg_list_first(categories); 3194 element != NULL; 3195 element = cfg_list_next(element)) 3196 { 3197 const cfg_obj_t *catobj; 3198 const char *str; 3199 3200 obj = cfg_listelt_value(element); 3201 catobj = cfg_tuple_get(obj, "name"); 3202 str = cfg_obj_asstring(catobj); 3203 if (strcasecmp(str, "queries") == 0) 3204 server->log_queries = ISC_TRUE; 3205 } 3206 } 3207 } 3208 } 3209 3210 obj = NULL; 3211 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS) 3212 if (cfg_obj_isvoid(obj)) 3213 ns_os_writepidfile(NULL, first_time); 3214 else 3215 ns_os_writepidfile(cfg_obj_asstring(obj), first_time); 3216 else if (ns_g_lwresdonly) 3217 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time); 3218 else 3219 ns_os_writepidfile(ns_g_defaultpidfile, first_time); 3220 3221 obj = NULL; 3222 if (options != NULL && 3223 cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS) 3224 ns_main_setmemstats(cfg_obj_asstring(obj)); 3225 else 3226 ns_main_setmemstats(NULL); 3227 3228 obj = NULL; 3229 result = ns_config_get(maps, "statistics-file", &obj); 3230 INSIST(result == ISC_R_SUCCESS); 3231 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)), 3232 "strdup"); 3233 3234 obj = NULL; 3235 result = ns_config_get(maps, "dump-file", &obj); 3236 INSIST(result == ISC_R_SUCCESS); 3237 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)), 3238 "strdup"); 3239 3240 obj = NULL; 3241 result = ns_config_get(maps, "recursing-file", &obj); 3242 INSIST(result == ISC_R_SUCCESS); 3243 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)), 3244 "strdup"); 3245 3246 obj = NULL; 3247 result = ns_config_get(maps, "version", &obj); 3248 if (result == ISC_R_SUCCESS) { 3249 CHECKM(setoptstring(server, &server->version, obj), "strdup"); 3250 server->version_set = ISC_TRUE; 3251 } else { 3252 server->version_set = ISC_FALSE; 3253 } 3254 3255 obj = NULL; 3256 result = ns_config_get(maps, "hostname", &obj); 3257 if (result == ISC_R_SUCCESS) { 3258 CHECKM(setoptstring(server, &server->hostname, obj), "strdup"); 3259 server->hostname_set = ISC_TRUE; 3260 } else { 3261 server->hostname_set = ISC_FALSE; 3262 } 3263 3264 obj = NULL; 3265 result = ns_config_get(maps, "server-id", &obj); 3266 server->server_usehostname = ISC_FALSE; 3267 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) { 3268 server->server_usehostname = ISC_TRUE; 3269 } else if (result == ISC_R_SUCCESS) { 3270 CHECKM(setoptstring(server, &server->server_id, obj), "strdup"); 3271 } else { 3272 result = setstring(server, &server->server_id, NULL); 3273 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3274 } 3275 3276 obj = NULL; 3277 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj); 3278 if (result == ISC_R_SUCCESS) { 3279 server->flushonshutdown = cfg_obj_asboolean(obj); 3280 } else { 3281 server->flushonshutdown = ISC_FALSE; 3282 } 3283 3284 result = ISC_R_SUCCESS; 3285 3286 cleanup: 3287 cfg_aclconfctx_destroy(&aclconfctx); 3288 3289 if (parser != NULL) { 3290 if (config != NULL) 3291 cfg_obj_destroy(parser, &config); 3292 cfg_parser_destroy(&parser); 3293 } 3294 3295 if (view != NULL) 3296 dns_view_detach(&view); 3297 3298 /* 3299 * This cleans up either the old production view list 3300 * or our temporary list depending on whether they 3301 * were swapped above or not. 3302 */ 3303 for (view = ISC_LIST_HEAD(viewlist); 3304 view != NULL; 3305 view = view_next) { 3306 view_next = ISC_LIST_NEXT(view, link); 3307 ISC_LIST_UNLINK(viewlist, view, link); 3308 if (result == ISC_R_SUCCESS && 3309 strcmp(view->name, "_bind") != 0) 3310 (void)dns_zt_apply(view->zonetable, ISC_FALSE, 3311 removed, view); 3312 dns_view_detach(&view); 3313 } 3314 3315 /* 3316 * Adjust the listening interfaces in accordance with the source 3317 * addresses specified in views and zones. 3318 */ 3319 if (isc_net_probeipv6() == ISC_R_SUCCESS) 3320 adjust_interfaces(server, ns_g_mctx); 3321 3322 /* Relinquish exclusive access to configuration data. */ 3323 isc_task_endexclusive(server->task); 3324 3325 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3326 ISC_LOG_DEBUG(1), "load_configuration: %s", 3327 isc_result_totext(result)); 3328 3329 return (result); 3330} 3331 3332static isc_result_t 3333load_zones(ns_server_t *server, isc_boolean_t stop) { 3334 isc_result_t result; 3335 dns_view_t *view; 3336 3337 result = isc_task_beginexclusive(server->task); 3338 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3339 3340 /* 3341 * Load zone data from disk. 3342 */ 3343 for (view = ISC_LIST_HEAD(server->viewlist); 3344 view != NULL; 3345 view = ISC_LIST_NEXT(view, link)) 3346 { 3347 CHECK(dns_view_load(view, stop)); 3348 } 3349 3350 /* 3351 * Force zone maintenance. Do this after loading 3352 * so that we know when we need to force AXFR of 3353 * slave zones whose master files are missing. 3354 */ 3355 CHECK(dns_zonemgr_forcemaint(server->zonemgr)); 3356 cleanup: 3357 isc_task_endexclusive(server->task); 3358 return (result); 3359} 3360 3361static isc_result_t 3362load_new_zones(ns_server_t *server, isc_boolean_t stop) { 3363 isc_result_t result; 3364 dns_view_t *view; 3365 3366 result = isc_task_beginexclusive(server->task); 3367 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3368 3369 /* 3370 * Load zone data from disk. 3371 */ 3372 for (view = ISC_LIST_HEAD(server->viewlist); 3373 view != NULL; 3374 view = ISC_LIST_NEXT(view, link)) 3375 { 3376 CHECK(dns_view_loadnew(view, stop)); 3377 } 3378 /* 3379 * Force zone maintenance. Do this after loading 3380 * so that we know when we need to force AXFR of 3381 * slave zones whose master files are missing. 3382 */ 3383 dns_zonemgr_resumexfrs(server->zonemgr); 3384 cleanup: 3385 isc_task_endexclusive(server->task); 3386 return (result); 3387} 3388 3389static void 3390run_server(isc_task_t *task, isc_event_t *event) { 3391 isc_result_t result; 3392 ns_server_t *server = (ns_server_t *)event->ev_arg; 3393 3394 INSIST(task == server->task); 3395 3396 isc_event_free(&event); 3397 3398 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy, 3399 &ns_g_dispatchmgr), 3400 "creating dispatch manager"); 3401 3402 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr, 3403 ns_g_socketmgr, ns_g_dispatchmgr, 3404 &server->interfacemgr), 3405 "creating interface manager"); 3406 3407 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 3408 NULL, NULL, server->task, 3409 interface_timer_tick, 3410 server, &server->interface_timer), 3411 "creating interface timer"); 3412 3413 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 3414 NULL, NULL, server->task, 3415 heartbeat_timer_tick, 3416 server, &server->heartbeat_timer), 3417 "creating heartbeat timer"); 3418 3419 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive, 3420 NULL, NULL, server->task, pps_timer_tick, 3421 server, &server->pps_timer), 3422 "creating pps timer"); 3423 3424 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser), 3425 "creating default configuration parser"); 3426 3427 if (ns_g_lwresdonly) 3428 CHECKFATAL(load_configuration(lwresd_g_conffile, server, 3429 ISC_TRUE), 3430 "loading configuration"); 3431 else 3432 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE), 3433 "loading configuration"); 3434 3435 isc_hash_init(); 3436 3437 CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones"); 3438 3439 ns_os_started(); 3440 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3441 ISC_LOG_NOTICE, "running"); 3442} 3443 3444void 3445ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) { 3446 3447 REQUIRE(NS_SERVER_VALID(server)); 3448 3449 server->flushonshutdown = flush; 3450} 3451 3452static void 3453shutdown_server(isc_task_t *task, isc_event_t *event) { 3454 isc_result_t result; 3455 dns_view_t *view, *view_next; 3456 ns_server_t *server = (ns_server_t *)event->ev_arg; 3457 isc_boolean_t flush = server->flushonshutdown; 3458 3459 UNUSED(task); 3460 INSIST(task == server->task); 3461 3462 result = isc_task_beginexclusive(server->task); 3463 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3464 3465 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3466 ISC_LOG_INFO, "shutting down%s", 3467 flush ? ": flushing changes" : ""); 3468 3469 ns_controls_shutdown(server->controls); 3470 end_reserved_dispatches(server, ISC_TRUE); 3471 3472 cfg_obj_destroy(ns_g_parser, &ns_g_config); 3473 cfg_parser_destroy(&ns_g_parser); 3474 3475 for (view = ISC_LIST_HEAD(server->viewlist); 3476 view != NULL; 3477 view = view_next) { 3478 view_next = ISC_LIST_NEXT(view, link); 3479 ISC_LIST_UNLINK(server->viewlist, view, link); 3480 if (flush) 3481 dns_view_flushanddetach(&view); 3482 else 3483 dns_view_detach(&view); 3484 } 3485 3486 isc_timer_detach(&server->interface_timer); 3487 isc_timer_detach(&server->heartbeat_timer); 3488 isc_timer_detach(&server->pps_timer); 3489 3490 ns_interfacemgr_shutdown(server->interfacemgr); 3491 ns_interfacemgr_detach(&server->interfacemgr); 3492 3493 dns_dispatchmgr_destroy(&ns_g_dispatchmgr); 3494 3495 dns_zonemgr_shutdown(server->zonemgr); 3496 3497 if (server->blackholeacl != NULL) 3498 dns_acl_detach(&server->blackholeacl); 3499 3500 dns_db_detach(&server->in_roothints); 3501 3502 isc_task_endexclusive(server->task); 3503 3504 isc_task_detach(&server->task); 3505 3506 isc_event_free(&event); 3507} 3508 3509void 3510ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { 3511 isc_result_t result; 3512 3513 ns_server_t *server = isc_mem_get(mctx, sizeof(*server)); 3514 if (server == NULL) 3515 fatal("allocating server object", ISC_R_NOMEMORY); 3516 3517 server->mctx = mctx; 3518 server->task = NULL; 3519 3520 /* Initialize configuration data with default values. */ 3521 3522 result = isc_quota_init(&server->xfroutquota, 10); 3523 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3524 result = isc_quota_init(&server->tcpquota, 10); 3525 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3526 result = isc_quota_init(&server->recursionquota, 100); 3527 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3528 3529 result = dns_aclenv_init(mctx, &server->aclenv); 3530 RUNTIME_CHECK(result == ISC_R_SUCCESS); 3531 3532 /* Initialize server data structures. */ 3533 server->zonemgr = NULL; 3534 server->interfacemgr = NULL; 3535 ISC_LIST_INIT(server->viewlist); 3536 server->in_roothints = NULL; 3537 server->blackholeacl = NULL; 3538 3539 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL, 3540 &server->in_roothints), 3541 "setting up root hints"); 3542 3543 CHECKFATAL(isc_mutex_init(&server->reload_event_lock), 3544 "initializing reload event lock"); 3545 server->reload_event = 3546 isc_event_allocate(ns_g_mctx, server, 3547 NS_EVENT_RELOAD, 3548 ns_server_reload, 3549 server, 3550 sizeof(isc_event_t)); 3551 CHECKFATAL(server->reload_event == NULL ? 3552 ISC_R_NOMEMORY : ISC_R_SUCCESS, 3553 "allocating reload event"); 3554 3555 CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY), 3556 "initializing DST"); 3557 3558 server->tkeyctx = NULL; 3559 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy, 3560 &server->tkeyctx), 3561 "creating TKEY context"); 3562 3563 /* 3564 * Setup the server task, which is responsible for coordinating 3565 * startup and shutdown of the server. 3566 */ 3567 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task), 3568 "creating server task"); 3569 isc_task_setname(server->task, "server", server); 3570 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server), 3571 "isc_task_onshutdown"); 3572 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server), 3573 "isc_app_onrun"); 3574 3575 server->interface_timer = NULL; 3576 server->heartbeat_timer = NULL; 3577 server->pps_timer = NULL; 3578 3579 server->interface_interval = 0; 3580 server->heartbeat_interval = 0; 3581 3582 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, 3583 ns_g_socketmgr, &server->zonemgr), 3584 "dns_zonemgr_create"); 3585 3586 server->statsfile = isc_mem_strdup(server->mctx, "named.stats"); 3587 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3588 "isc_mem_strdup"); 3589 server->querystats = NULL; 3590 3591 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db"); 3592 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3593 "isc_mem_strdup"); 3594 3595 server->recfile = isc_mem_strdup(server->mctx, "named.recursing"); 3596 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS, 3597 "isc_mem_strdup"); 3598 3599 server->hostname_set = ISC_FALSE; 3600 server->hostname = NULL; 3601 server->version_set = ISC_FALSE; 3602 server->version = NULL; 3603 server->server_usehostname = ISC_FALSE; 3604 server->server_id = NULL; 3605 3606 CHECKFATAL(dns_stats_alloccounters(ns_g_mctx, &server->querystats), 3607 "dns_stats_alloccounters"); 3608 3609 server->flushonshutdown = ISC_FALSE; 3610 server->log_queries = ISC_FALSE; 3611 3612 server->controls = NULL; 3613 CHECKFATAL(ns_controls_create(server, &server->controls), 3614 "ns_controls_create"); 3615 server->dispatchgen = 0; 3616 ISC_LIST_INIT(server->dispatches); 3617 3618 server->magic = NS_SERVER_MAGIC; 3619 *serverp = server; 3620} 3621 3622void 3623ns_server_destroy(ns_server_t **serverp) { 3624 ns_server_t *server = *serverp; 3625 REQUIRE(NS_SERVER_VALID(server)); 3626 3627 ns_controls_destroy(&server->controls); 3628 3629 dns_stats_freecounters(server->mctx, &server->querystats); 3630 3631 isc_mem_free(server->mctx, server->statsfile); 3632 isc_mem_free(server->mctx, server->dumpfile); 3633 isc_mem_free(server->mctx, server->recfile); 3634 3635 if (server->version != NULL) 3636 isc_mem_free(server->mctx, server->version); 3637 if (server->hostname != NULL) 3638 isc_mem_free(server->mctx, server->hostname); 3639 if (server->server_id != NULL) 3640 isc_mem_free(server->mctx, server->server_id); 3641 3642 dns_zonemgr_detach(&server->zonemgr); 3643 3644 if (server->tkeyctx != NULL) 3645 dns_tkeyctx_destroy(&server->tkeyctx); 3646 3647 dst_lib_destroy(); 3648 3649 isc_event_free(&server->reload_event); 3650 3651 INSIST(ISC_LIST_EMPTY(server->viewlist)); 3652 3653 dns_aclenv_destroy(&server->aclenv); 3654 3655 isc_quota_destroy(&server->recursionquota); 3656 isc_quota_destroy(&server->tcpquota); 3657 isc_quota_destroy(&server->xfroutquota); 3658 3659 server->magic = 0; 3660 isc_mem_put(server->mctx, server, sizeof(*server)); 3661 *serverp = NULL; 3662} 3663 3664static void 3665fatal(const char *msg, isc_result_t result) { 3666 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3667 ISC_LOG_CRITICAL, "%s: %s", msg, 3668 isc_result_totext(result)); 3669 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, 3670 ISC_LOG_CRITICAL, "exiting (due to fatal error)"); 3671 exit(1); 3672} 3673 3674static void 3675start_reserved_dispatches(ns_server_t *server) { 3676 3677 REQUIRE(NS_SERVER_VALID(server)); 3678 3679 server->dispatchgen++; 3680} 3681 3682static void 3683end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) { 3684 ns_dispatch_t *dispatch, *nextdispatch; 3685 3686 REQUIRE(NS_SERVER_VALID(server)); 3687 3688 for (dispatch = ISC_LIST_HEAD(server->dispatches); 3689 dispatch != NULL; 3690 dispatch = nextdispatch) { 3691 nextdispatch = ISC_LIST_NEXT(dispatch, link); 3692 if (!all && server->dispatchgen == dispatch-> dispatchgen) 3693 continue; 3694 ISC_LIST_UNLINK(server->dispatches, dispatch, link); 3695 dns_dispatch_detach(&dispatch->dispatch); 3696 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 3697 } 3698} 3699 3700void 3701ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) { 3702 ns_dispatch_t *dispatch; 3703 in_port_t port; 3704 char addrbuf[ISC_SOCKADDR_FORMATSIZE]; 3705 isc_result_t result; 3706 unsigned int attrs, attrmask; 3707 3708 REQUIRE(NS_SERVER_VALID(server)); 3709 3710 port = isc_sockaddr_getport(addr); 3711 if (port == 0 || port >= 1024) 3712 return; 3713 3714 for (dispatch = ISC_LIST_HEAD(server->dispatches); 3715 dispatch != NULL; 3716 dispatch = ISC_LIST_NEXT(dispatch, link)) { 3717 if (isc_sockaddr_equal(&dispatch->addr, addr)) 3718 break; 3719 } 3720 if (dispatch != NULL) { 3721 dispatch->dispatchgen = server->dispatchgen; 3722 return; 3723 } 3724 3725 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch)); 3726 if (dispatch == NULL) { 3727 result = ISC_R_NOMEMORY; 3728 goto cleanup; 3729 } 3730 3731 dispatch->addr = *addr; 3732 dispatch->dispatchgen = server->dispatchgen; 3733 dispatch->dispatch = NULL; 3734 3735 attrs = 0; 3736 attrs |= DNS_DISPATCHATTR_UDP; 3737 switch (isc_sockaddr_pf(addr)) { 3738 case AF_INET: 3739 attrs |= DNS_DISPATCHATTR_IPV4; 3740 break; 3741 case AF_INET6: 3742 attrs |= DNS_DISPATCHATTR_IPV6; 3743 break; 3744 default: 3745 result = ISC_R_NOTIMPLEMENTED; 3746 goto cleanup; 3747 } 3748 attrmask = 0; 3749 attrmask |= DNS_DISPATCHATTR_UDP; 3750 attrmask |= DNS_DISPATCHATTR_TCP; 3751 attrmask |= DNS_DISPATCHATTR_IPV4; 3752 attrmask |= DNS_DISPATCHATTR_IPV6; 3753 3754 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr, 3755 ns_g_taskmgr, &dispatch->addr, 4096, 3756 1000, 32768, 16411, 16433, 3757 attrs, attrmask, &dispatch->dispatch); 3758 if (result != ISC_R_SUCCESS) 3759 goto cleanup; 3760 3761 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link); 3762 3763 return; 3764 3765 cleanup: 3766 if (dispatch != NULL) 3767 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch)); 3768 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); 3769 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3770 NS_LOGMODULE_SERVER, ISC_LOG_WARNING, 3771 "unable to create dispatch for reserved port %s: %s", 3772 addrbuf, isc_result_totext(result)); 3773} 3774 3775 3776static isc_result_t 3777loadconfig(ns_server_t *server) { 3778 isc_result_t result; 3779 start_reserved_dispatches(server); 3780 result = load_configuration(ns_g_lwresdonly ? 3781 lwresd_g_conffile : ns_g_conffile, 3782 server, ISC_FALSE); 3783 if (result == ISC_R_SUCCESS) 3784 end_reserved_dispatches(server, ISC_FALSE); 3785 else 3786 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3787 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3788 "reloading configuration failed: %s", 3789 isc_result_totext(result)); 3790 return (result); 3791} 3792 3793static isc_result_t 3794reload(ns_server_t *server) { 3795 isc_result_t result; 3796 CHECK(loadconfig(server)); 3797 3798 result = load_zones(server, ISC_FALSE); 3799 if (result != ISC_R_SUCCESS) { 3800 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3801 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3802 "reloading zones failed: %s", 3803 isc_result_totext(result)); 3804 } 3805 cleanup: 3806 return (result); 3807} 3808 3809static void 3810reconfig(ns_server_t *server) { 3811 isc_result_t result; 3812 CHECK(loadconfig(server)); 3813 3814 result = load_new_zones(server, ISC_FALSE); 3815 if (result != ISC_R_SUCCESS) { 3816 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 3817 NS_LOGMODULE_SERVER, ISC_LOG_ERROR, 3818 "loading new zones failed: %s", 3819 isc_result_totext(result)); 3820 } 3821 cleanup: ; 3822} 3823 3824/* 3825 * Handle a reload event (from SIGHUP). 3826 */ 3827static void 3828ns_server_reload(isc_task_t *task, isc_event_t *event) { 3829 ns_server_t *server = (ns_server_t *)event->ev_arg; 3830 3831 INSIST(task = server->task); 3832 UNUSED(task); 3833 3834 (void)reload(server); 3835 3836 LOCK(&server->reload_event_lock); 3837 INSIST(server->reload_event == NULL); 3838 server->reload_event = event; 3839 UNLOCK(&server->reload_event_lock); 3840} 3841 3842void 3843ns_server_reloadwanted(ns_server_t *server) { 3844 LOCK(&server->reload_event_lock); 3845 if (server->reload_event != NULL) 3846 isc_task_send(server->task, &server->reload_event); 3847 UNLOCK(&server->reload_event_lock); 3848} 3849 3850static char * 3851next_token(char **stringp, const char *delim) { 3852 char *res; 3853 3854 do { 3855 res = strsep(stringp, delim); 3856 if (res == NULL) 3857 break; 3858 } while (*res == '\0'); 3859 return (res); 3860} 3861 3862/* 3863 * Find the zone specified in the control channel command 'args', 3864 * if any. If a zone is specified, point '*zonep' at it, otherwise 3865 * set '*zonep' to NULL. 3866 */ 3867static isc_result_t 3868zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) { 3869 char *input, *ptr; 3870 const char *zonetxt; 3871 char *classtxt; 3872 const char *viewtxt = NULL; 3873 dns_fixedname_t name; 3874 isc_result_t result; 3875 isc_buffer_t buf; 3876 dns_view_t *view = NULL; 3877 dns_rdataclass_t rdclass; 3878 3879 REQUIRE(zonep != NULL && *zonep == NULL); 3880 3881 input = args; 3882 3883 /* Skip the command name. */ 3884 ptr = next_token(&input, " \t"); 3885 if (ptr == NULL) 3886 return (ISC_R_UNEXPECTEDEND); 3887 3888 /* Look for the zone name. */ 3889 zonetxt = next_token(&input, " \t"); 3890 if (zonetxt == NULL) 3891 return (ISC_R_SUCCESS); 3892 3893 /* Look for the optional class name. */ 3894 classtxt = next_token(&input, " \t"); 3895 if (classtxt != NULL) { 3896 /* Look for the optional view name. */ 3897 viewtxt = next_token(&input, " \t"); 3898 } 3899 3900 isc_buffer_init(&buf, zonetxt, strlen(zonetxt)); 3901 isc_buffer_add(&buf, strlen(zonetxt)); 3902 dns_fixedname_init(&name); 3903 result = dns_name_fromtext(dns_fixedname_name(&name), 3904 &buf, dns_rootname, ISC_FALSE, NULL); 3905 if (result != ISC_R_SUCCESS) 3906 goto fail1; 3907 3908 if (classtxt != NULL) { 3909 isc_textregion_t r; 3910 r.base = classtxt; 3911 r.length = strlen(classtxt); 3912 result = dns_rdataclass_fromtext(&rdclass, &r); 3913 if (result != ISC_R_SUCCESS) 3914 goto fail1; 3915 } else { 3916 rdclass = dns_rdataclass_in; 3917 } 3918 3919 if (viewtxt == NULL) 3920 viewtxt = "_default"; 3921 result = dns_viewlist_find(&server->viewlist, viewtxt, 3922 rdclass, &view); 3923 if (result != ISC_R_SUCCESS) 3924 goto fail1; 3925 3926 result = dns_zt_find(view->zonetable, dns_fixedname_name(&name), 3927 0, NULL, zonep); 3928 /* Partial match? */ 3929 if (result != ISC_R_SUCCESS && *zonep != NULL) 3930 dns_zone_detach(zonep); 3931 dns_view_detach(&view); 3932 fail1: 3933 return (result); 3934} 3935 3936/* 3937 * Act on a "retransfer" command from the command channel. 3938 */ 3939isc_result_t 3940ns_server_retransfercommand(ns_server_t *server, char *args) { 3941 isc_result_t result; 3942 dns_zone_t *zone = NULL; 3943 dns_zonetype_t type; 3944 3945 result = zone_from_args(server, args, &zone); 3946 if (result != ISC_R_SUCCESS) 3947 return (result); 3948 if (zone == NULL) 3949 return (ISC_R_UNEXPECTEDEND); 3950 type = dns_zone_gettype(zone); 3951 if (type == dns_zone_slave || type == dns_zone_stub) 3952 dns_zone_forcereload(zone); 3953 else 3954 result = ISC_R_NOTFOUND; 3955 dns_zone_detach(&zone); 3956 return (result); 3957} 3958 3959/* 3960 * Act on a "reload" command from the command channel. 3961 */ 3962isc_result_t 3963ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 3964 isc_result_t result; 3965 dns_zone_t *zone = NULL; 3966 dns_zonetype_t type; 3967 const char *msg = NULL; 3968 3969 result = zone_from_args(server, args, &zone); 3970 if (result != ISC_R_SUCCESS) 3971 return (result); 3972 if (zone == NULL) { 3973 result = reload(server); 3974 if (result == ISC_R_SUCCESS) 3975 msg = "server reload successful"; 3976 } else { 3977 type = dns_zone_gettype(zone); 3978 if (type == dns_zone_slave || type == dns_zone_stub) { 3979 dns_zone_refresh(zone); 3980 msg = "zone refresh queued"; 3981 } else { 3982 result = dns_zone_load(zone); 3983 dns_zone_detach(&zone); 3984 switch (result) { 3985 case ISC_R_SUCCESS: 3986 msg = "zone reload successful"; 3987 break; 3988 case DNS_R_CONTINUE: 3989 msg = "zone reload queued"; 3990 result = ISC_R_SUCCESS; 3991 break; 3992 case DNS_R_UPTODATE: 3993 msg = "zone reload up-to-date"; 3994 result = ISC_R_SUCCESS; 3995 break; 3996 default: 3997 /* failure message will be generated by rndc */ 3998 break; 3999 } 4000 } 4001 } 4002 if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) 4003 isc_buffer_putmem(text, (const unsigned char *)msg, 4004 strlen(msg) + 1); 4005 return (result); 4006} 4007 4008/* 4009 * Act on a "reconfig" command from the command channel. 4010 */ 4011isc_result_t 4012ns_server_reconfigcommand(ns_server_t *server, char *args) { 4013 UNUSED(args); 4014 4015 reconfig(server); 4016 return (ISC_R_SUCCESS); 4017} 4018 4019/* 4020 * Act on a "notify" command from the command channel. 4021 */ 4022isc_result_t 4023ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) { 4024 isc_result_t result; 4025 dns_zone_t *zone = NULL; 4026 const unsigned char msg[] = "zone notify queued"; 4027 4028 result = zone_from_args(server, args, &zone); 4029 if (result != ISC_R_SUCCESS) 4030 return (result); 4031 if (zone == NULL) 4032 return (ISC_R_UNEXPECTEDEND); 4033 4034 dns_zone_notify(zone); 4035 dns_zone_detach(&zone); 4036 if (sizeof(msg) <= isc_buffer_availablelength(text)) 4037 isc_buffer_putmem(text, msg, sizeof(msg)); 4038 4039 return (ISC_R_SUCCESS); 4040} 4041 4042/* 4043 * Act on a "refresh" command from the command channel. 4044 */ 4045isc_result_t 4046ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { 4047 isc_result_t result; 4048 dns_zone_t *zone = NULL; 4049 const unsigned char msg1[] = "zone refresh queued"; 4050 const unsigned char msg2[] = "not a slave or stub zone"; 4051 dns_zonetype_t type; 4052 4053 result = zone_from_args(server, args, &zone); 4054 if (result != ISC_R_SUCCESS) 4055 return (result); 4056 if (zone == NULL) 4057 return (ISC_R_UNEXPECTEDEND); 4058 4059 type = dns_zone_gettype(zone); 4060 if (type == dns_zone_slave || type == dns_zone_stub) { 4061 dns_zone_refresh(zone); 4062 dns_zone_detach(&zone); 4063 if (sizeof(msg1) <= isc_buffer_availablelength(text)) 4064 isc_buffer_putmem(text, msg1, sizeof(msg1)); 4065 return (ISC_R_SUCCESS); 4066 } 4067 4068 dns_zone_detach(&zone); 4069 if (sizeof(msg2) <= isc_buffer_availablelength(text)) 4070 isc_buffer_putmem(text, msg2, sizeof(msg2)); 4071 return (ISC_R_FAILURE); 4072} 4073 4074isc_result_t 4075ns_server_togglequerylog(ns_server_t *server) { 4076 server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE; 4077 4078 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4079 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4080 "query logging is now %s", 4081 server->log_queries ? "on" : "off"); 4082 return (ISC_R_SUCCESS); 4083} 4084 4085static isc_result_t 4086ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config, 4087 cfg_aclconfctx_t *actx, 4088 isc_mem_t *mctx, ns_listenlist_t **target) 4089{ 4090 isc_result_t result; 4091 const cfg_listelt_t *element; 4092 ns_listenlist_t *dlist = NULL; 4093 4094 REQUIRE(target != NULL && *target == NULL); 4095 4096 result = ns_listenlist_create(mctx, &dlist); 4097 if (result != ISC_R_SUCCESS) 4098 return (result); 4099 4100 for (element = cfg_list_first(listenlist); 4101 element != NULL; 4102 element = cfg_list_next(element)) 4103 { 4104 ns_listenelt_t *delt = NULL; 4105 const cfg_obj_t *listener = cfg_listelt_value(element); 4106 result = ns_listenelt_fromconfig(listener, config, actx, 4107 mctx, &delt); 4108 if (result != ISC_R_SUCCESS) 4109 goto cleanup; 4110 ISC_LIST_APPEND(dlist->elts, delt, link); 4111 } 4112 *target = dlist; 4113 return (ISC_R_SUCCESS); 4114 4115 cleanup: 4116 ns_listenlist_detach(&dlist); 4117 return (result); 4118} 4119 4120/* 4121 * Create a listen list from the corresponding configuration 4122 * data structure. 4123 */ 4124static isc_result_t 4125ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, 4126 cfg_aclconfctx_t *actx, 4127 isc_mem_t *mctx, ns_listenelt_t **target) 4128{ 4129 isc_result_t result; 4130 const cfg_obj_t *portobj; 4131 in_port_t port; 4132 ns_listenelt_t *delt = NULL; 4133 REQUIRE(target != NULL && *target == NULL); 4134 4135 portobj = cfg_tuple_get(listener, "port"); 4136 if (!cfg_obj_isuint32(portobj)) { 4137 if (ns_g_port != 0) { 4138 port = ns_g_port; 4139 } else { 4140 result = ns_config_getport(config, &port); 4141 if (result != ISC_R_SUCCESS) 4142 return (result); 4143 } 4144 } else { 4145 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { 4146 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, 4147 "port value '%u' is out of range", 4148 cfg_obj_asuint32(portobj)); 4149 return (ISC_R_RANGE); 4150 } 4151 port = (in_port_t)cfg_obj_asuint32(portobj); 4152 } 4153 4154 result = ns_listenelt_create(mctx, port, NULL, &delt); 4155 if (result != ISC_R_SUCCESS) 4156 return (result); 4157 4158 result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"), 4159 config, ns_g_lctx, actx, mctx, &delt->acl); 4160 if (result != ISC_R_SUCCESS) { 4161 ns_listenelt_destroy(delt); 4162 return (result); 4163 } 4164 *target = delt; 4165 return (ISC_R_SUCCESS); 4166} 4167 4168isc_result_t 4169ns_server_dumpstats(ns_server_t *server) { 4170 isc_result_t result; 4171 dns_zone_t *zone, *next; 4172 isc_stdtime_t now; 4173 FILE *fp = NULL; 4174 int i; 4175 int ncounters; 4176 4177 isc_stdtime_get(&now); 4178 4179 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp), 4180 "could not open statistics dump file", server->statsfile); 4181 4182 ncounters = DNS_STATS_NCOUNTERS; 4183 fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now); 4184 4185 for (i = 0; i < ncounters; i++) 4186 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n", 4187 dns_statscounter_names[i], 4188 server->querystats[i]); 4189 4190 zone = NULL; 4191 for (result = dns_zone_first(server->zonemgr, &zone); 4192 result == ISC_R_SUCCESS; 4193 next = NULL, result = dns_zone_next(zone, &next), zone = next) 4194 { 4195 isc_uint64_t *zonestats = dns_zone_getstatscounters(zone); 4196 if (zonestats != NULL) { 4197 char zonename[DNS_NAME_FORMATSIZE]; 4198 dns_view_t *view; 4199 char *viewname; 4200 4201 dns_name_format(dns_zone_getorigin(zone), 4202 zonename, sizeof(zonename)); 4203 view = dns_zone_getview(zone); 4204 viewname = view->name; 4205 for (i = 0; i < ncounters; i++) { 4206 fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT 4207 "u %s", 4208 dns_statscounter_names[i], 4209 zonestats[i], 4210 zonename); 4211 if (strcmp(viewname, "_default") != 0) 4212 fprintf(fp, " %s", viewname); 4213 fprintf(fp, "\n"); 4214 } 4215 } 4216 } 4217 if (result == ISC_R_NOMORE) 4218 result = ISC_R_SUCCESS; 4219 CHECK(result); 4220 4221 fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now); 4222 4223 cleanup: 4224 if (fp != NULL) 4225 (void)isc_stdio_close(fp); 4226 return (result); 4227} 4228 4229static isc_result_t 4230add_zone_tolist(dns_zone_t *zone, void *uap) { 4231 struct dumpcontext *dctx = uap; 4232 struct zonelistentry *zle; 4233 4234 zle = isc_mem_get(dctx->mctx, sizeof *zle); 4235 if (zle == NULL) 4236 return (ISC_R_NOMEMORY); 4237 zle->zone = NULL; 4238 dns_zone_attach(zone, &zle->zone); 4239 ISC_LINK_INIT(zle, link); 4240 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link); 4241 return (ISC_R_SUCCESS); 4242} 4243 4244static isc_result_t 4245add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) { 4246 struct viewlistentry *vle; 4247 isc_result_t result = ISC_R_SUCCESS; 4248 4249 /* 4250 * Prevent duplicate views. 4251 */ 4252 for (vle = ISC_LIST_HEAD(dctx->viewlist); 4253 vle != NULL; 4254 vle = ISC_LIST_NEXT(vle, link)) 4255 if (vle->view == view) 4256 return (ISC_R_SUCCESS); 4257 4258 vle = isc_mem_get(dctx->mctx, sizeof *vle); 4259 if (vle == NULL) 4260 return (ISC_R_NOMEMORY); 4261 vle->view = NULL; 4262 dns_view_attach(view, &vle->view); 4263 ISC_LINK_INIT(vle, link); 4264 ISC_LIST_INIT(vle->zonelist); 4265 ISC_LIST_APPEND(dctx->viewlist, vle, link); 4266 if (dctx->dumpzones) 4267 result = dns_zt_apply(view->zonetable, ISC_TRUE, 4268 add_zone_tolist, dctx); 4269 return (result); 4270} 4271 4272static void 4273dumpcontext_destroy(struct dumpcontext *dctx) { 4274 struct viewlistentry *vle; 4275 struct zonelistentry *zle; 4276 4277 vle = ISC_LIST_HEAD(dctx->viewlist); 4278 while (vle != NULL) { 4279 ISC_LIST_UNLINK(dctx->viewlist, vle, link); 4280 zle = ISC_LIST_HEAD(vle->zonelist); 4281 while (zle != NULL) { 4282 ISC_LIST_UNLINK(vle->zonelist, zle, link); 4283 dns_zone_detach(&zle->zone); 4284 isc_mem_put(dctx->mctx, zle, sizeof *zle); 4285 zle = ISC_LIST_HEAD(vle->zonelist); 4286 } 4287 dns_view_detach(&vle->view); 4288 isc_mem_put(dctx->mctx, vle, sizeof *vle); 4289 vle = ISC_LIST_HEAD(dctx->viewlist); 4290 } 4291 if (dctx->version != NULL) 4292 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE); 4293 if (dctx->db != NULL) 4294 dns_db_detach(&dctx->db); 4295 if (dctx->cache != NULL) 4296 dns_db_detach(&dctx->cache); 4297 if (dctx->task != NULL) 4298 isc_task_detach(&dctx->task); 4299 if (dctx->fp != NULL) 4300 (void)isc_stdio_close(dctx->fp); 4301 if (dctx->mdctx != NULL) 4302 dns_dumpctx_detach(&dctx->mdctx); 4303 isc_mem_put(dctx->mctx, dctx, sizeof *dctx); 4304} 4305 4306static void 4307dumpdone(void *arg, isc_result_t result) { 4308 struct dumpcontext *dctx = arg; 4309 char buf[1024+32]; 4310 const dns_master_style_t *style; 4311 4312 if (result != ISC_R_SUCCESS) 4313 goto cleanup; 4314 if (dctx->mdctx != NULL) 4315 dns_dumpctx_detach(&dctx->mdctx); 4316 if (dctx->view == NULL) { 4317 dctx->view = ISC_LIST_HEAD(dctx->viewlist); 4318 if (dctx->view == NULL) 4319 goto done; 4320 INSIST(dctx->zone == NULL); 4321 } else 4322 goto resume; 4323 nextview: 4324 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name); 4325 resume: 4326 if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) { 4327 style = &dns_master_style_cache; 4328 /* start cache dump */ 4329 if (dctx->view->view->cachedb != NULL) 4330 dns_db_attach(dctx->view->view->cachedb, &dctx->cache); 4331 if (dctx->cache != NULL) { 4332 4333 fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n", 4334 dctx->view->view->name); 4335 result = dns_master_dumptostreaminc(dctx->mctx, 4336 dctx->cache, NULL, 4337 style, dctx->fp, 4338 dctx->task, 4339 dumpdone, dctx, 4340 &dctx->mdctx); 4341 if (result == DNS_R_CONTINUE) 4342 return; 4343 if (result == ISC_R_NOTIMPLEMENTED) 4344 fprintf(dctx->fp, "; %s\n", 4345 dns_result_totext(result)); 4346 else if (result != ISC_R_SUCCESS) 4347 goto cleanup; 4348 } 4349 } 4350 if (dctx->cache != NULL) { 4351 dns_adb_dump(dctx->view->view->adb, dctx->fp); 4352 dns_db_detach(&dctx->cache); 4353 } 4354 if (dctx->dumpzones) { 4355 style = &dns_master_style_full; 4356 nextzone: 4357 if (dctx->version != NULL) 4358 dns_db_closeversion(dctx->db, &dctx->version, 4359 ISC_FALSE); 4360 if (dctx->db != NULL) 4361 dns_db_detach(&dctx->db); 4362 if (dctx->zone == NULL) 4363 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist); 4364 else 4365 dctx->zone = ISC_LIST_NEXT(dctx->zone, link); 4366 if (dctx->zone != NULL) { 4367 /* start zone dump */ 4368 dns_zone_name(dctx->zone->zone, buf, sizeof(buf)); 4369 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf); 4370 result = dns_zone_getdb(dctx->zone->zone, &dctx->db); 4371 if (result != ISC_R_SUCCESS) { 4372 fprintf(dctx->fp, "; %s\n", 4373 dns_result_totext(result)); 4374 goto nextzone; 4375 } 4376 dns_db_currentversion(dctx->db, &dctx->version); 4377 result = dns_master_dumptostreaminc(dctx->mctx, 4378 dctx->db, 4379 dctx->version, 4380 style, dctx->fp, 4381 dctx->task, 4382 dumpdone, dctx, 4383 &dctx->mdctx); 4384 if (result == DNS_R_CONTINUE) 4385 return; 4386 if (result == ISC_R_NOTIMPLEMENTED) { 4387 fprintf(dctx->fp, "; %s\n", 4388 dns_result_totext(result)); 4389 result = ISC_R_SUCCESS; 4390 goto nextzone; 4391 } 4392 if (result != ISC_R_SUCCESS) 4393 goto cleanup; 4394 } 4395 } 4396 if (dctx->view != NULL) 4397 dctx->view = ISC_LIST_NEXT(dctx->view, link); 4398 if (dctx->view != NULL) 4399 goto nextview; 4400 done: 4401 fprintf(dctx->fp, "; Dump complete\n"); 4402 result = isc_stdio_flush(dctx->fp); 4403 if (result == ISC_R_SUCCESS) 4404 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4405 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4406 "dumpdb complete"); 4407 cleanup: 4408 if (result != ISC_R_SUCCESS) 4409 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4410 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4411 "dumpdb failed: %s", dns_result_totext(result)); 4412 dumpcontext_destroy(dctx); 4413} 4414 4415isc_result_t 4416ns_server_dumpdb(ns_server_t *server, char *args) { 4417 struct dumpcontext *dctx = NULL; 4418 dns_view_t *view; 4419 isc_result_t result; 4420 char *ptr; 4421 const char *sep; 4422 4423 /* Skip the command name. */ 4424 ptr = next_token(&args, " \t"); 4425 if (ptr == NULL) 4426 return (ISC_R_UNEXPECTEDEND); 4427 4428 dctx = isc_mem_get(server->mctx, sizeof(*dctx)); 4429 if (dctx == NULL) 4430 return (ISC_R_NOMEMORY); 4431 4432 dctx->mctx = server->mctx; 4433 dctx->dumpcache = ISC_TRUE; 4434 dctx->dumpzones = ISC_FALSE; 4435 dctx->fp = NULL; 4436 ISC_LIST_INIT(dctx->viewlist); 4437 dctx->view = NULL; 4438 dctx->zone = NULL; 4439 dctx->cache = NULL; 4440 dctx->mdctx = NULL; 4441 dctx->db = NULL; 4442 dctx->cache = NULL; 4443 dctx->task = NULL; 4444 dctx->version = NULL; 4445 isc_task_attach(server->task, &dctx->task); 4446 4447 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), 4448 "could not open dump file", server->dumpfile); 4449 4450 sep = (args == NULL) ? "" : ": "; 4451 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4452 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4453 "dumpdb started%s%s", sep, (args != NULL) ? args : ""); 4454 4455 ptr = next_token(&args, " \t"); 4456 if (ptr != NULL && strcmp(ptr, "-all") == 0) { 4457 dctx->dumpzones = ISC_TRUE; 4458 dctx->dumpcache = ISC_TRUE; 4459 ptr = next_token(&args, " \t"); 4460 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { 4461 dctx->dumpzones = ISC_FALSE; 4462 dctx->dumpcache = ISC_TRUE; 4463 ptr = next_token(&args, " \t"); 4464 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { 4465 dctx->dumpzones = ISC_TRUE; 4466 dctx->dumpcache = ISC_FALSE; 4467 ptr = next_token(&args, " \t"); 4468 } 4469 4470 nextview: 4471 for (view = ISC_LIST_HEAD(server->viewlist); 4472 view != NULL; 4473 view = ISC_LIST_NEXT(view, link)) 4474 { 4475 if (ptr != NULL && strcmp(view->name, ptr) != 0) 4476 continue; 4477 CHECK(add_view_tolist(dctx, view)); 4478 } 4479 if (ptr != NULL) { 4480 ptr = next_token(&args, " \t"); 4481 if (ptr != NULL) 4482 goto nextview; 4483 } 4484 dumpdone(dctx, ISC_R_SUCCESS); 4485 return (ISC_R_SUCCESS); 4486 4487 cleanup: 4488 if (dctx != NULL) 4489 dumpcontext_destroy(dctx); 4490 return (result); 4491} 4492 4493isc_result_t 4494ns_server_dumprecursing(ns_server_t *server) { 4495 FILE *fp = NULL; 4496 isc_result_t result; 4497 4498 CHECKMF(isc_stdio_open(server->recfile, "w", &fp), 4499 "could not open dump file", server->recfile); 4500 fprintf(fp,";\n; Recursing Queries\n;\n"); 4501 ns_interfacemgr_dumprecursing(fp, server->interfacemgr); 4502 fprintf(fp, "; Dump complete\n"); 4503 4504 cleanup: 4505 if (fp != NULL) 4506 result = isc_stdio_close(fp); 4507 return (result); 4508} 4509 4510isc_result_t 4511ns_server_setdebuglevel(ns_server_t *server, char *args) { 4512 char *ptr; 4513 char *levelstr; 4514 char *endp; 4515 long newlevel; 4516 4517 UNUSED(server); 4518 4519 /* Skip the command name. */ 4520 ptr = next_token(&args, " \t"); 4521 if (ptr == NULL) 4522 return (ISC_R_UNEXPECTEDEND); 4523 4524 /* Look for the new level name. */ 4525 levelstr = next_token(&args, " \t"); 4526 if (levelstr == NULL) { 4527 if (ns_g_debuglevel < 99) 4528 ns_g_debuglevel++; 4529 } else { 4530 newlevel = strtol(levelstr, &endp, 10); 4531 if (*endp != '\0' || newlevel < 0 || newlevel > 99) 4532 return (ISC_R_RANGE); 4533 ns_g_debuglevel = (unsigned int)newlevel; 4534 } 4535 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); 4536 return (ISC_R_SUCCESS); 4537} 4538 4539isc_result_t 4540ns_server_validation(ns_server_t *server, char *args) { 4541 char *ptr, *viewname; 4542 dns_view_t *view; 4543 isc_boolean_t changed = ISC_FALSE; 4544 isc_result_t result; 4545 isc_boolean_t enable; 4546 4547 /* Skip the command name. */ 4548 ptr = next_token(&args, " \t"); 4549 if (ptr == NULL) 4550 return (ISC_R_UNEXPECTEDEND); 4551 4552 /* Find out what we are to do. */ 4553 ptr = next_token(&args, " \t"); 4554 if (ptr == NULL) 4555 return (ISC_R_UNEXPECTEDEND); 4556 4557 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || 4558 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) 4559 enable = ISC_TRUE; 4560 else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || 4561 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) 4562 enable = ISC_FALSE; 4563 else 4564 return (DNS_R_SYNTAX); 4565 4566 /* Look for the view name. */ 4567 viewname = next_token(&args, " \t"); 4568 4569 result = isc_task_beginexclusive(server->task); 4570 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4571 for (view = ISC_LIST_HEAD(server->viewlist); 4572 view != NULL; 4573 view = ISC_LIST_NEXT(view, link)) 4574 { 4575 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 4576 continue; 4577 result = dns_view_flushcache(view); 4578 if (result != ISC_R_SUCCESS) 4579 goto out; 4580 view->enablevalidation = enable; 4581 changed = ISC_TRUE; 4582 } 4583 if (changed) 4584 result = ISC_R_SUCCESS; 4585 else 4586 result = ISC_R_FAILURE; 4587 out: 4588 isc_task_endexclusive(server->task); 4589 return (result); 4590} 4591 4592isc_result_t 4593ns_server_flushcache(ns_server_t *server, char *args) { 4594 char *ptr, *viewname; 4595 dns_view_t *view; 4596 isc_boolean_t flushed = ISC_FALSE; 4597 isc_result_t result; 4598 4599 /* Skip the command name. */ 4600 ptr = next_token(&args, " \t"); 4601 if (ptr == NULL) 4602 return (ISC_R_UNEXPECTEDEND); 4603 4604 /* Look for the view name. */ 4605 viewname = next_token(&args, " \t"); 4606 4607 result = isc_task_beginexclusive(server->task); 4608 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4609 for (view = ISC_LIST_HEAD(server->viewlist); 4610 view != NULL; 4611 view = ISC_LIST_NEXT(view, link)) 4612 { 4613 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 4614 continue; 4615 result = dns_view_flushcache(view); 4616 if (result != ISC_R_SUCCESS) 4617 goto out; 4618 flushed = ISC_TRUE; 4619 } 4620 if (flushed) 4621 result = ISC_R_SUCCESS; 4622 else 4623 result = ISC_R_FAILURE; 4624 out: 4625 isc_task_endexclusive(server->task); 4626 return (result); 4627} 4628 4629isc_result_t 4630ns_server_flushname(ns_server_t *server, char *args) { 4631 char *ptr, *target, *viewname; 4632 dns_view_t *view; 4633 isc_boolean_t flushed = ISC_FALSE; 4634 isc_result_t result; 4635 isc_buffer_t b; 4636 dns_fixedname_t fixed; 4637 dns_name_t *name; 4638 4639 /* Skip the command name. */ 4640 ptr = next_token(&args, " \t"); 4641 if (ptr == NULL) 4642 return (ISC_R_UNEXPECTEDEND); 4643 4644 /* Find the domain name to flush. */ 4645 target = next_token(&args, " \t"); 4646 if (target == NULL) 4647 return (ISC_R_UNEXPECTEDEND); 4648 4649 isc_buffer_init(&b, target, strlen(target)); 4650 isc_buffer_add(&b, strlen(target)); 4651 dns_fixedname_init(&fixed); 4652 name = dns_fixedname_name(&fixed); 4653 result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); 4654 if (result != ISC_R_SUCCESS) 4655 return (result); 4656 4657 /* Look for the view name. */ 4658 viewname = next_token(&args, " \t"); 4659 4660 result = isc_task_beginexclusive(server->task); 4661 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4662 flushed = ISC_TRUE; 4663 for (view = ISC_LIST_HEAD(server->viewlist); 4664 view != NULL; 4665 view = ISC_LIST_NEXT(view, link)) 4666 { 4667 if (viewname != NULL && strcasecmp(viewname, view->name) != 0) 4668 continue; 4669 result = dns_view_flushname(view, name); 4670 if (result != ISC_R_SUCCESS) 4671 flushed = ISC_FALSE; 4672 } 4673 if (flushed) 4674 result = ISC_R_SUCCESS; 4675 else 4676 result = ISC_R_FAILURE; 4677 isc_task_endexclusive(server->task); 4678 return (result); 4679} 4680 4681isc_result_t 4682ns_server_status(ns_server_t *server, isc_buffer_t *text) { 4683 int zonecount, xferrunning, xferdeferred, soaqueries; 4684 unsigned int n; 4685 4686 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY); 4687 xferrunning = dns_zonemgr_getcount(server->zonemgr, 4688 DNS_ZONESTATE_XFERRUNNING); 4689 xferdeferred = dns_zonemgr_getcount(server->zonemgr, 4690 DNS_ZONESTATE_XFERDEFERRED); 4691 soaqueries = dns_zonemgr_getcount(server->zonemgr, 4692 DNS_ZONESTATE_SOAQUERY); 4693 n = snprintf((char *)isc_buffer_used(text), 4694 isc_buffer_availablelength(text), 4695 "number of zones: %u\n" 4696 "debug level: %d\n" 4697 "xfers running: %u\n" 4698 "xfers deferred: %u\n" 4699 "soa queries in progress: %u\n" 4700 "query logging is %s\n" 4701 "recursive clients: %d/%d/%d\n" 4702 "tcp clients: %d/%d\n" 4703 "server is up and running", 4704 zonecount, ns_g_debuglevel, xferrunning, xferdeferred, 4705 soaqueries, server->log_queries ? "ON" : "OFF", 4706 server->recursionquota.used, server->recursionquota.soft, 4707 server->recursionquota.max, 4708 server->tcpquota.used, server->tcpquota.max); 4709 if (n >= isc_buffer_availablelength(text)) 4710 return (ISC_R_NOSPACE); 4711 isc_buffer_add(text, n); 4712 return (ISC_R_SUCCESS); 4713} 4714 4715/* 4716 * Act on a "freeze" or "thaw" command from the command channel. 4717 */ 4718isc_result_t 4719ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) { 4720 isc_result_t result, tresult; 4721 dns_zone_t *zone = NULL; 4722 dns_zonetype_t type; 4723 char classstr[DNS_RDATACLASS_FORMATSIZE]; 4724 char zonename[DNS_NAME_FORMATSIZE]; 4725 dns_view_t *view; 4726 char *journal; 4727 const char *vname, *sep; 4728 isc_boolean_t frozen; 4729 4730 result = zone_from_args(server, args, &zone); 4731 if (result != ISC_R_SUCCESS) 4732 return (result); 4733 if (zone == NULL) { 4734 result = isc_task_beginexclusive(server->task); 4735 RUNTIME_CHECK(result == ISC_R_SUCCESS); 4736 tresult = ISC_R_SUCCESS; 4737 for (view = ISC_LIST_HEAD(server->viewlist); 4738 view != NULL; 4739 view = ISC_LIST_NEXT(view, link)) { 4740 result = dns_view_freezezones(view, freeze); 4741 if (result != ISC_R_SUCCESS && 4742 tresult == ISC_R_SUCCESS) 4743 tresult = result; 4744 } 4745 isc_task_endexclusive(server->task); 4746 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4747 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4748 "%s all zones: %s", 4749 freeze ? "freezing" : "thawing", 4750 isc_result_totext(tresult)); 4751 return (tresult); 4752 } 4753 type = dns_zone_gettype(zone); 4754 if (type != dns_zone_master) { 4755 dns_zone_detach(&zone); 4756 return (ISC_R_NOTFOUND); 4757 } 4758 4759 frozen = dns_zone_getupdatedisabled(zone); 4760 if (freeze) { 4761 if (frozen) 4762 result = DNS_R_FROZEN; 4763 if (result == ISC_R_SUCCESS) 4764 result = dns_zone_flush(zone); 4765 if (result == ISC_R_SUCCESS) { 4766 journal = dns_zone_getjournal(zone); 4767 if (journal != NULL) 4768 (void)isc_file_remove(journal); 4769 } 4770 } else { 4771 if (frozen) { 4772 result = dns_zone_load(zone); 4773 if (result == DNS_R_CONTINUE || 4774 result == DNS_R_UPTODATE) 4775 result = ISC_R_SUCCESS; 4776 } 4777 } 4778 if (result == ISC_R_SUCCESS) 4779 dns_zone_setupdatedisabled(zone, freeze); 4780 4781 view = dns_zone_getview(zone); 4782 if (strcmp(view->name, "_bind") == 0 || 4783 strcmp(view->name, "_default") == 0) 4784 { 4785 vname = ""; 4786 sep = ""; 4787 } else { 4788 vname = view->name; 4789 sep = " "; 4790 } 4791 dns_rdataclass_format(dns_zone_getclass(zone), classstr, 4792 sizeof(classstr)); 4793 dns_name_format(dns_zone_getorigin(zone), 4794 zonename, sizeof(zonename)); 4795 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 4796 NS_LOGMODULE_SERVER, ISC_LOG_INFO, 4797 "%s zone '%s/%s'%s%s: %s", 4798 freeze ? "freezing" : "thawing", 4799 zonename, classstr, sep, vname, 4800 isc_result_totext(result)); 4801 dns_zone_detach(&zone); 4802 return (result); 4803} 4804 4805#ifdef HAVE_LIBSCF 4806/* 4807 * This function adds a message for rndc to echo if named 4808 * is managed by smf and is also running chroot. 4809 */ 4810isc_result_t 4811ns_smf_add_message(isc_buffer_t *text) { 4812 unsigned int n; 4813 4814 n = snprintf((char *)isc_buffer_used(text), 4815 isc_buffer_availablelength(text), 4816 "use svcadm(1M) to manage named"); 4817 if (n >= isc_buffer_availablelength(text)) 4818 return (ISC_R_NOSPACE); 4819 isc_buffer_add(text, n); 4820 return (ISC_R_SUCCESS); 4821} 4822#endif /* HAVE_LIBSCF */ 4823