00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <limits.h>
00025 #include <ctype.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028
00029 #include <isc/app.h>
00030 #include <isc/base64.h>
00031 #include <isc/dir.h>
00032 #include <isc/entropy.h>
00033 #include <isc/file.h>
00034 #include <isc/hash.h>
00035 #include <isc/hex.h>
00036 #include <isc/httpd.h>
00037 #include <isc/lex.h>
00038 #include <isc/parseint.h>
00039 #include <isc/portset.h>
00040 #include <isc/print.h>
00041 #include <isc/random.h>
00042 #include <isc/refcount.h>
00043 #include <isc/resource.h>
00044 #include <isc/sha2.h>
00045 #include <isc/socket.h>
00046 #include <isc/stat.h>
00047 #include <isc/stats.h>
00048 #include <isc/stdio.h>
00049 #include <isc/string.h>
00050 #include <isc/task.h>
00051 #include <isc/timer.h>
00052 #include <isc/util.h>
00053 #include <isc/xml.h>
00054
00055 #ifdef AES_SIT
00056 #include <isc/aes.h>
00057 #else
00058 #include <isc/hmacsha.h>
00059 #endif
00060
00061 #include <isccfg/grammar.h>
00062 #include <isccfg/namedconf.h>
00063
00064 #include <bind9/check.h>
00065
00066 #include <dns/acache.h>
00067 #include <dns/adb.h>
00068 #include <dns/badcache.h>
00069 #include <dns/cache.h>
00070 #include <dns/db.h>
00071 #include <dns/dispatch.h>
00072 #include <dns/dlz.h>
00073 #include <dns/dns64.h>
00074 #include <dns/forward.h>
00075 #include <dns/journal.h>
00076 #include <dns/keytable.h>
00077 #include <dns/keyvalues.h>
00078 #include <dns/lib.h>
00079 #include <dns/master.h>
00080 #include <dns/masterdump.h>
00081 #include <dns/nta.h>
00082 #include <dns/order.h>
00083 #include <dns/peer.h>
00084 #include <dns/portlist.h>
00085 #include <dns/private.h>
00086 #include <dns/rbt.h>
00087 #include <dns/rdataclass.h>
00088 #include <dns/rdatalist.h>
00089 #include <dns/rdataset.h>
00090 #include <dns/rdatastruct.h>
00091 #include <dns/resolver.h>
00092 #include <dns/rootns.h>
00093 #include <dns/rriterator.h>
00094 #include <dns/secalg.h>
00095 #include <dns/soa.h>
00096 #include <dns/stats.h>
00097 #include <dns/tkey.h>
00098 #include <dns/tsig.h>
00099 #include <dns/ttl.h>
00100 #include <dns/view.h>
00101 #include <dns/zone.h>
00102 #include <dns/zt.h>
00103
00104 #include <dst/dst.h>
00105 #include <dst/result.h>
00106
00107 #include <named/client.h>
00108 #include <named/config.h>
00109 #include <named/control.h>
00110 #include <named/geoip.h>
00111 #include <named/interfacemgr.h>
00112 #include <named/log.h>
00113 #include <named/logconf.h>
00114 #include <named/lwresd.h>
00115 #include <named/main.h>
00116 #include <named/os.h>
00117 #include <named/server.h>
00118 #include <named/statschannel.h>
00119 #include <named/tkeyconf.h>
00120 #include <named/tsigconf.h>
00121 #include <named/zoneconf.h>
00122 #ifdef HAVE_LIBSCF
00123 #include <named/ns_smf_globals.h>
00124 #include <stdlib.h>
00125 #endif
00126 #ifdef HAVE_GEOIP
00127 #include <named/geoip.h>
00128 #endif
00129
00130 #ifndef PATH_MAX
00131 #define PATH_MAX 1024
00132 #endif
00133
00134 #ifndef SIZE_MAX
00135 #define SIZE_MAX ((size_t)-1)
00136 #endif
00137
00138 #ifdef TUNE_LARGE
00139 #define RESOLVER_NTASKS 523
00140 #define UDPBUFFERS 32768
00141 #define EXCLBUFFERS 32768
00142 #else
00143 #define RESOLVER_NTASKS 31
00144 #define UDPBUFFERS 1000
00145 #define EXCLBUFFERS 4096
00146 #endif
00147
00148
00149
00150
00151
00152 #define CHECK(op) \
00153 do { result = (op); \
00154 if (result != ISC_R_SUCCESS) goto cleanup; \
00155 } while (0)
00156
00157 #define TCHECK(op) \
00158 do { tresult = (op); \
00159 if (tresult != ISC_R_SUCCESS) { \
00160 isc_buffer_clear(*text); \
00161 goto cleanup; \
00162 } \
00163 } while (0)
00164
00165 #define CHECKM(op, msg) \
00166 do { result = (op); \
00167 if (result != ISC_R_SUCCESS) { \
00168 isc_log_write(ns_g_lctx, \
00169 NS_LOGCATEGORY_GENERAL, \
00170 NS_LOGMODULE_SERVER, \
00171 ISC_LOG_ERROR, \
00172 "%s: %s", msg, \
00173 isc_result_totext(result)); \
00174 goto cleanup; \
00175 } \
00176 } while (0) \
00177
00178 #define CHECKMF(op, msg, file) \
00179 do { result = (op); \
00180 if (result != ISC_R_SUCCESS) { \
00181 isc_log_write(ns_g_lctx, \
00182 NS_LOGCATEGORY_GENERAL, \
00183 NS_LOGMODULE_SERVER, \
00184 ISC_LOG_ERROR, \
00185 "%s '%s': %s", msg, file, \
00186 isc_result_totext(result)); \
00187 goto cleanup; \
00188 } \
00189 } while (0) \
00190
00191 #define CHECKFATAL(op, msg) \
00192 do { result = (op); \
00193 if (result != ISC_R_SUCCESS) \
00194 fatal(msg, result); \
00195 } while (0) \
00196
00197
00198
00199
00200
00201
00202
00203 #define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U
00204
00205 struct ns_dispatch {
00206 isc_sockaddr_t addr;
00207 unsigned int dispatchgen;
00208 dns_dispatch_t *dispatch;
00209 ISC_LINK(struct ns_dispatch) link;
00210 };
00211
00212 struct ns_cache {
00213 dns_cache_t *cache;
00214 dns_view_t *primaryview;
00215 isc_boolean_t needflush;
00216 isc_boolean_t adbsizeadjusted;
00217 ISC_LINK(ns_cache_t) link;
00218 };
00219
00220 struct dumpcontext {
00221 isc_mem_t *mctx;
00222 isc_boolean_t dumpcache;
00223 isc_boolean_t dumpzones;
00224 FILE *fp;
00225 ISC_LIST(struct viewlistentry) viewlist;
00226 struct viewlistentry *view;
00227 struct zonelistentry *zone;
00228 dns_dumpctx_t *mdctx;
00229 dns_db_t *db;
00230 dns_db_t *cache;
00231 isc_task_t *task;
00232 dns_dbversion_t *version;
00233 };
00234
00235 struct viewlistentry {
00236 dns_view_t *view;
00237 ISC_LINK(struct viewlistentry) link;
00238 ISC_LIST(struct zonelistentry) zonelist;
00239 };
00240
00241 struct zonelistentry {
00242 dns_zone_t *zone;
00243 ISC_LINK(struct zonelistentry) link;
00244 };
00245
00246
00247
00248
00249
00250 typedef struct ns_cfgctx {
00251 isc_mem_t * mctx;
00252 cfg_parser_t * conf_parser;
00253 cfg_parser_t * add_parser;
00254 cfg_obj_t * config;
00255 cfg_obj_t * vconfig;
00256 cfg_obj_t * nzconfig;
00257 cfg_aclconfctx_t * actx;
00258 } ns_cfgctx_t;
00259
00260
00261
00262
00263
00264
00265 typedef struct {
00266 ns_server_t *server;
00267 isc_refcount_t refs;
00268 } ns_zoneload_t;
00269
00270
00271
00272
00273 const char *empty_zones[] = {
00274
00275 "10.IN-ADDR.ARPA",
00276 "16.172.IN-ADDR.ARPA",
00277 "17.172.IN-ADDR.ARPA",
00278 "18.172.IN-ADDR.ARPA",
00279 "19.172.IN-ADDR.ARPA",
00280 "20.172.IN-ADDR.ARPA",
00281 "21.172.IN-ADDR.ARPA",
00282 "22.172.IN-ADDR.ARPA",
00283 "23.172.IN-ADDR.ARPA",
00284 "24.172.IN-ADDR.ARPA",
00285 "25.172.IN-ADDR.ARPA",
00286 "26.172.IN-ADDR.ARPA",
00287 "27.172.IN-ADDR.ARPA",
00288 "28.172.IN-ADDR.ARPA",
00289 "29.172.IN-ADDR.ARPA",
00290 "30.172.IN-ADDR.ARPA",
00291 "31.172.IN-ADDR.ARPA",
00292 "168.192.IN-ADDR.ARPA",
00293
00294
00295 "64.100.IN-ADDR.ARPA",
00296 "65.100.IN-ADDR.ARPA",
00297 "66.100.IN-ADDR.ARPA",
00298 "67.100.IN-ADDR.ARPA",
00299 "68.100.IN-ADDR.ARPA",
00300 "69.100.IN-ADDR.ARPA",
00301 "70.100.IN-ADDR.ARPA",
00302 "71.100.IN-ADDR.ARPA",
00303 "72.100.IN-ADDR.ARPA",
00304 "73.100.IN-ADDR.ARPA",
00305 "74.100.IN-ADDR.ARPA",
00306 "75.100.IN-ADDR.ARPA",
00307 "76.100.IN-ADDR.ARPA",
00308 "77.100.IN-ADDR.ARPA",
00309 "78.100.IN-ADDR.ARPA",
00310 "79.100.IN-ADDR.ARPA",
00311 "80.100.IN-ADDR.ARPA",
00312 "81.100.IN-ADDR.ARPA",
00313 "82.100.IN-ADDR.ARPA",
00314 "83.100.IN-ADDR.ARPA",
00315 "84.100.IN-ADDR.ARPA",
00316 "85.100.IN-ADDR.ARPA",
00317 "86.100.IN-ADDR.ARPA",
00318 "87.100.IN-ADDR.ARPA",
00319 "88.100.IN-ADDR.ARPA",
00320 "89.100.IN-ADDR.ARPA",
00321 "90.100.IN-ADDR.ARPA",
00322 "91.100.IN-ADDR.ARPA",
00323 "92.100.IN-ADDR.ARPA",
00324 "93.100.IN-ADDR.ARPA",
00325 "94.100.IN-ADDR.ARPA",
00326 "95.100.IN-ADDR.ARPA",
00327 "96.100.IN-ADDR.ARPA",
00328 "97.100.IN-ADDR.ARPA",
00329 "98.100.IN-ADDR.ARPA",
00330 "99.100.IN-ADDR.ARPA",
00331 "100.100.IN-ADDR.ARPA",
00332 "101.100.IN-ADDR.ARPA",
00333 "102.100.IN-ADDR.ARPA",
00334 "103.100.IN-ADDR.ARPA",
00335 "104.100.IN-ADDR.ARPA",
00336 "105.100.IN-ADDR.ARPA",
00337 "106.100.IN-ADDR.ARPA",
00338 "107.100.IN-ADDR.ARPA",
00339 "108.100.IN-ADDR.ARPA",
00340 "109.100.IN-ADDR.ARPA",
00341 "110.100.IN-ADDR.ARPA",
00342 "111.100.IN-ADDR.ARPA",
00343 "112.100.IN-ADDR.ARPA",
00344 "113.100.IN-ADDR.ARPA",
00345 "114.100.IN-ADDR.ARPA",
00346 "115.100.IN-ADDR.ARPA",
00347 "116.100.IN-ADDR.ARPA",
00348 "117.100.IN-ADDR.ARPA",
00349 "118.100.IN-ADDR.ARPA",
00350 "119.100.IN-ADDR.ARPA",
00351 "120.100.IN-ADDR.ARPA",
00352 "121.100.IN-ADDR.ARPA",
00353 "122.100.IN-ADDR.ARPA",
00354 "123.100.IN-ADDR.ARPA",
00355 "124.100.IN-ADDR.ARPA",
00356 "125.100.IN-ADDR.ARPA",
00357 "126.100.IN-ADDR.ARPA",
00358 "127.100.IN-ADDR.ARPA",
00359
00360
00361 "0.IN-ADDR.ARPA",
00362 "127.IN-ADDR.ARPA",
00363 "254.169.IN-ADDR.ARPA",
00364 "2.0.192.IN-ADDR.ARPA",
00365 "100.51.198.IN-ADDR.ARPA",
00366 "113.0.203.IN-ADDR.ARPA",
00367 "255.255.255.255.IN-ADDR.ARPA",
00368
00369
00370 "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",
00371 "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",
00372
00373 "D.F.IP6.ARPA",
00374 "8.E.F.IP6.ARPA",
00375 "9.E.F.IP6.ARPA",
00376 "A.E.F.IP6.ARPA",
00377 "B.E.F.IP6.ARPA",
00378
00379
00380 "8.B.D.0.1.0.0.2.IP6.ARPA",
00381
00382 NULL
00383 };
00384
00385 ISC_PLATFORM_NORETURN_PRE static void
00386 fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
00387
00388 static void
00389 ns_server_reload(isc_task_t *task, isc_event_t *event);
00390
00391 static isc_result_t
00392 ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
00393 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
00394 isc_uint16_t family, ns_listenelt_t **target);
00395 static isc_result_t
00396 ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
00397 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
00398 isc_uint16_t family, ns_listenlist_t **target);
00399
00400 static isc_result_t
00401 configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
00402 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype);
00403
00404 static isc_result_t
00405 configure_alternates(const cfg_obj_t *config, dns_view_t *view,
00406 const cfg_obj_t *alternates);
00407
00408 static isc_result_t
00409 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
00410 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
00411 dns_viewlist_t *viewlist, cfg_aclconfctx_t *aclconf,
00412 isc_boolean_t added, isc_boolean_t old_rpz_ok,
00413 isc_boolean_t modify);
00414
00415 static isc_result_t
00416 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx);
00417
00418 static void
00419 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
00420
00421 static void
00422 newzone_cfgctx_destroy(void **cfgp);
00423
00424 static inline isc_result_t
00425 putstr(isc_buffer_t **b, const char *str);
00426
00427 static isc_result_t
00428 putmem(isc_buffer_t **b, const char *str, size_t len);
00429
00430 static isc_result_t
00431 putuint8(isc_buffer_t **b, isc_uint8_t val);
00432
00433 static inline isc_result_t
00434 putnull(isc_buffer_t **b);
00435
00436 static isc_result_t
00437 add_comment(FILE *fp, const char *viewname);
00438
00439
00440
00441
00442
00443 static isc_result_t
00444 configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
00445 const char *aclname, const char *acltuplename,
00446 cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp)
00447 {
00448 isc_result_t result;
00449 const cfg_obj_t *maps[3];
00450 const cfg_obj_t *aclobj = NULL;
00451 int i = 0;
00452
00453 if (*aclp != NULL)
00454 dns_acl_detach(aclp);
00455 if (vconfig != NULL)
00456 maps[i++] = cfg_tuple_get(vconfig, "options");
00457 if (config != NULL) {
00458 const cfg_obj_t *options = NULL;
00459 (void)cfg_map_get(config, "options", &options);
00460 if (options != NULL)
00461 maps[i++] = options;
00462 }
00463 maps[i] = NULL;
00464
00465 (void)ns_config_get(maps, aclname, &aclobj);
00466 if (aclobj == NULL)
00467
00468
00469
00470 return (ISC_R_SUCCESS);
00471
00472 if (acltuplename != NULL) {
00473
00474
00475
00476
00477
00478 aclobj = cfg_tuple_get(aclobj, acltuplename);
00479 }
00480
00481 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
00482 actx, mctx, 0, aclp);
00483
00484 return (result);
00485 }
00486
00487
00488
00489
00490
00491
00492 static isc_result_t
00493 configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
00494 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
00495 dns_acl_t **aclp)
00496 {
00497 isc_result_t result;
00498 const cfg_obj_t *maps[3];
00499 const cfg_obj_t *aclobj = NULL;
00500 int i = 0;
00501
00502 if (*aclp != NULL)
00503 dns_acl_detach(aclp);
00504 if (vconfig != NULL)
00505 maps[i++] = cfg_tuple_get(vconfig, "options");
00506 if (config != NULL) {
00507 const cfg_obj_t *options = NULL;
00508 (void)cfg_map_get(config, "options", &options);
00509 if (options != NULL)
00510 maps[i++] = options;
00511 }
00512 maps[i] = NULL;
00513
00514 (void)ns_config_get(maps, "sortlist", &aclobj);
00515 if (aclobj == NULL)
00516 return (ISC_R_SUCCESS);
00517
00518
00519
00520
00521
00522
00523
00524 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
00525 actx, mctx, 3, aclp);
00526
00527 return (result);
00528 }
00529
00530 static isc_result_t
00531 configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
00532 const char *confname, const char *conftuplename,
00533 isc_mem_t *mctx, dns_rbt_t **rbtp)
00534 {
00535 isc_result_t result;
00536 const cfg_obj_t *maps[3];
00537 const cfg_obj_t *obj = NULL;
00538 const cfg_listelt_t *element;
00539 int i = 0;
00540 dns_fixedname_t fixed;
00541 dns_name_t *name;
00542 isc_buffer_t b;
00543 const char *str;
00544 const cfg_obj_t *nameobj;
00545
00546 if (*rbtp != NULL)
00547 dns_rbt_destroy(rbtp);
00548 if (vconfig != NULL)
00549 maps[i++] = cfg_tuple_get(vconfig, "options");
00550 if (config != NULL) {
00551 const cfg_obj_t *options = NULL;
00552 (void)cfg_map_get(config, "options", &options);
00553 if (options != NULL)
00554 maps[i++] = options;
00555 }
00556 maps[i] = NULL;
00557
00558 (void)ns_config_get(maps, confname, &obj);
00559 if (obj == NULL)
00560
00561
00562
00563 return (ISC_R_SUCCESS);
00564
00565 if (conftuplename != NULL) {
00566 obj = cfg_tuple_get(obj, conftuplename);
00567 if (cfg_obj_isvoid(obj))
00568 return (ISC_R_SUCCESS);
00569 }
00570
00571 result = dns_rbt_create(mctx, NULL, NULL, rbtp);
00572 if (result != ISC_R_SUCCESS)
00573 return (result);
00574
00575 dns_fixedname_init(&fixed);
00576 name = dns_fixedname_name(&fixed);
00577 for (element = cfg_list_first(obj);
00578 element != NULL;
00579 element = cfg_list_next(element)) {
00580 nameobj = cfg_listelt_value(element);
00581 str = cfg_obj_asstring(nameobj);
00582 isc_buffer_constinit(&b, str, strlen(str));
00583 isc_buffer_add(&b, strlen(str));
00584 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
00585
00586
00587
00588
00589
00590
00591
00592 result = dns_rbt_addname(*rbtp, name, (void *)1);
00593 if (result != ISC_R_SUCCESS) {
00594 cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR,
00595 "failed to add %s for %s: %s",
00596 str, confname, isc_result_totext(result));
00597 goto cleanup;
00598 }
00599
00600 }
00601
00602 return (result);
00603
00604 cleanup:
00605 dns_rbt_destroy(rbtp);
00606 return (result);
00607
00608 }
00609
00610 static isc_result_t
00611 dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
00612 isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx)
00613 {
00614 dns_rdataclass_t viewclass;
00615 dns_rdata_dnskey_t keystruct;
00616 isc_uint32_t flags, proto, alg;
00617 const char *keystr, *keynamestr;
00618 unsigned char keydata[4096];
00619 isc_buffer_t keydatabuf;
00620 unsigned char rrdata[4096];
00621 isc_buffer_t rrdatabuf;
00622 isc_region_t r;
00623 dns_fixedname_t fkeyname;
00624 dns_name_t *keyname;
00625 isc_buffer_t namebuf;
00626 isc_result_t result;
00627 dst_key_t *dstkey = NULL;
00628
00629 INSIST(target != NULL && *target == NULL);
00630
00631 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
00632 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
00633 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
00634 keyname = dns_fixedname_name(&fkeyname);
00635 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
00636
00637 if (managed) {
00638 const char *initmethod;
00639 initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
00640
00641 if (strcasecmp(initmethod, "initial-key") != 0) {
00642 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
00643 "managed key '%s': "
00644 "invalid initialization method '%s'",
00645 keynamestr, initmethod);
00646 result = ISC_R_FAILURE;
00647 goto cleanup;
00648 }
00649 }
00650
00651 if (vconfig == NULL)
00652 viewclass = dns_rdataclass_in;
00653 else {
00654 const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
00655 CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
00656 &viewclass));
00657 }
00658 keystruct.common.rdclass = viewclass;
00659 keystruct.common.rdtype = dns_rdatatype_dnskey;
00660
00661
00662
00663 keystruct.mctx = NULL;
00664
00665 ISC_LINK_INIT(&keystruct.common, link);
00666
00667 if (flags > 0xffff)
00668 CHECKM(ISC_R_RANGE, "key flags");
00669 if (proto > 0xff)
00670 CHECKM(ISC_R_RANGE, "key protocol");
00671 if (alg > 0xff)
00672 CHECKM(ISC_R_RANGE, "key algorithm");
00673 keystruct.flags = (isc_uint16_t)flags;
00674 keystruct.protocol = (isc_uint8_t)proto;
00675 keystruct.algorithm = (isc_uint8_t)alg;
00676
00677 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
00678 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
00679
00680 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
00681 CHECK(isc_base64_decodestring(keystr, &keydatabuf));
00682 isc_buffer_usedregion(&keydatabuf, &r);
00683 keystruct.datalen = r.length;
00684 keystruct.data = r.base;
00685
00686 if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
00687 keystruct.algorithm == DST_ALG_RSAMD5) &&
00688 r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
00689 cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
00690 "%s key '%s' has a weak exponent",
00691 managed ? "managed" : "trusted",
00692 keynamestr);
00693
00694 CHECK(dns_rdata_fromstruct(NULL,
00695 keystruct.common.rdclass,
00696 keystruct.common.rdtype,
00697 &keystruct, &rrdatabuf));
00698 dns_fixedname_init(&fkeyname);
00699 isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr));
00700 isc_buffer_add(&namebuf, strlen(keynamestr));
00701 CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
00702 CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
00703 mctx, &dstkey));
00704
00705 *target = dstkey;
00706 return (ISC_R_SUCCESS);
00707
00708 cleanup:
00709 if (result == DST_R_NOCRYPTO) {
00710 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
00711 "ignoring %s key for '%s': no crypto support",
00712 managed ? "managed" : "trusted",
00713 keynamestr);
00714 } else if (result == DST_R_UNSUPPORTEDALG) {
00715 cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
00716 "skipping %s key for '%s': %s",
00717 managed ? "managed" : "trusted",
00718 keynamestr, isc_result_totext(result));
00719 } else {
00720 cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
00721 "configuring %s key for '%s': %s",
00722 managed ? "managed" : "trusted",
00723 keynamestr, isc_result_totext(result));
00724 result = ISC_R_FAILURE;
00725 }
00726
00727 if (dstkey != NULL)
00728 dst_key_free(&dstkey);
00729
00730 return (result);
00731 }
00732
00733 static isc_result_t
00734 load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
00735 dns_view_t *view, isc_boolean_t managed,
00736 dns_name_t *keyname, isc_mem_t *mctx)
00737 {
00738 const cfg_listelt_t *elt, *elt2;
00739 const cfg_obj_t *key, *keylist;
00740 dst_key_t *dstkey = NULL;
00741 isc_result_t result;
00742 dns_keytable_t *secroots = NULL;
00743
00744 CHECK(dns_view_getsecroots(view, &secroots));
00745
00746 for (elt = cfg_list_first(keys);
00747 elt != NULL;
00748 elt = cfg_list_next(elt)) {
00749 keylist = cfg_listelt_value(elt);
00750
00751 for (elt2 = cfg_list_first(keylist);
00752 elt2 != NULL;
00753 elt2 = cfg_list_next(elt2)) {
00754 key = cfg_listelt_value(elt2);
00755 result = dstkey_fromconfig(vconfig, key, managed,
00756 &dstkey, mctx);
00757 if (result == DST_R_UNSUPPORTEDALG) {
00758 result = ISC_R_SUCCESS;
00759 continue;
00760 }
00761 if (result != ISC_R_SUCCESS)
00762 goto cleanup;
00763
00764
00765
00766
00767 if (keyname != NULL &&
00768 !dns_name_equal(keyname, dst_key_name(dstkey)))
00769 {
00770 dst_key_free(&dstkey);
00771 continue;
00772 }
00773
00774 CHECK(dns_keytable_add(secroots, managed, &dstkey));
00775 }
00776 }
00777
00778 cleanup:
00779 if (dstkey != NULL)
00780 dst_key_free(&dstkey);
00781 if (secroots != NULL)
00782 dns_keytable_detach(&secroots);
00783 if (result == DST_R_NOCRYPTO)
00784 result = ISC_R_SUCCESS;
00785 return (result);
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 static isc_result_t
00795 configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
00796 const cfg_obj_t *config, const cfg_obj_t *bindkeys,
00797 isc_boolean_t auto_dlv, isc_boolean_t auto_root,
00798 isc_mem_t *mctx)
00799 {
00800 isc_result_t result = ISC_R_SUCCESS;
00801 const cfg_obj_t *view_keys = NULL;
00802 const cfg_obj_t *global_keys = NULL;
00803 const cfg_obj_t *view_managed_keys = NULL;
00804 const cfg_obj_t *global_managed_keys = NULL;
00805 const cfg_obj_t *maps[4];
00806 const cfg_obj_t *voptions = NULL;
00807 const cfg_obj_t *options = NULL;
00808 const cfg_obj_t *obj = NULL;
00809 const char *directory;
00810 int i = 0;
00811
00812
00813 if (strcmp(view->name, "_bind") == 0 &&
00814 view->rdclass == dns_rdataclass_chaos) {
00815 return (ISC_R_SUCCESS);
00816 }
00817
00818 if (vconfig != NULL) {
00819 voptions = cfg_tuple_get(vconfig, "options");
00820 if (voptions != NULL) {
00821 (void) cfg_map_get(voptions, "trusted-keys",
00822 &view_keys);
00823 (void) cfg_map_get(voptions, "managed-keys",
00824 &view_managed_keys);
00825 maps[i++] = voptions;
00826 }
00827 }
00828
00829 if (config != NULL) {
00830 (void)cfg_map_get(config, "trusted-keys", &global_keys);
00831 (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
00832 (void)cfg_map_get(config, "options", &options);
00833 if (options != NULL) {
00834 maps[i++] = options;
00835 }
00836 }
00837
00838 maps[i++] = ns_g_defaults;
00839 maps[i] = NULL;
00840
00841 result = dns_view_initsecroots(view, mctx);
00842 if (result != ISC_R_SUCCESS) {
00843 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00844 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
00845 "couldn't create keytable");
00846 return (ISC_R_UNEXPECTED);
00847 }
00848
00849 result = dns_view_initntatable(view, ns_g_taskmgr, ns_g_timermgr);
00850 if (result != ISC_R_SUCCESS) {
00851 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00852 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
00853 "couldn't create NTA table");
00854 return (ISC_R_UNEXPECTED);
00855 }
00856
00857 if (auto_dlv && view->rdclass == dns_rdataclass_in) {
00858 const cfg_obj_t *builtin_keys = NULL;
00859 const cfg_obj_t *builtin_managed_keys = NULL;
00860
00861 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
00862 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
00863 "using built-in DLV key for view %s",
00864 view->name);
00865
00866
00867
00868
00869
00870 if (bindkeys != NULL) {
00871 (void)cfg_map_get(bindkeys, "trusted-keys",
00872 &builtin_keys);
00873 (void)cfg_map_get(bindkeys, "managed-keys",
00874 &builtin_managed_keys);
00875 } else {
00876 (void)cfg_map_get(ns_g_config, "trusted-keys",
00877 &builtin_keys);
00878 (void)cfg_map_get(ns_g_config, "managed-keys",
00879 &builtin_managed_keys);
00880 }
00881
00882 if (builtin_keys != NULL)
00883 CHECK(load_view_keys(builtin_keys, vconfig, view,
00884 ISC_FALSE, view->dlv, mctx));
00885 if (builtin_managed_keys != NULL)
00886 CHECK(load_view_keys(builtin_managed_keys, vconfig,
00887 view, ISC_TRUE, view->dlv, mctx));
00888 }
00889
00890 if (auto_root && view->rdclass == dns_rdataclass_in) {
00891 const cfg_obj_t *builtin_keys = NULL;
00892 const cfg_obj_t *builtin_managed_keys = NULL;
00893
00894 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
00895 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
00896 "using built-in root key for view %s",
00897 view->name);
00898
00899
00900
00901
00902
00903 if (bindkeys != NULL) {
00904 (void)cfg_map_get(bindkeys, "trusted-keys",
00905 &builtin_keys);
00906 (void)cfg_map_get(bindkeys, "managed-keys",
00907 &builtin_managed_keys);
00908 } else {
00909 (void)cfg_map_get(ns_g_config, "trusted-keys",
00910 &builtin_keys);
00911 (void)cfg_map_get(ns_g_config, "managed-keys",
00912 &builtin_managed_keys);
00913 }
00914
00915 if (builtin_keys != NULL)
00916 CHECK(load_view_keys(builtin_keys, vconfig, view,
00917 ISC_FALSE, dns_rootname, mctx));
00918 if (builtin_managed_keys != NULL)
00919 CHECK(load_view_keys(builtin_managed_keys, vconfig,
00920 view, ISC_TRUE, dns_rootname,
00921 mctx));
00922 }
00923
00924 CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE,
00925 NULL, mctx));
00926 CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE,
00927 NULL, mctx));
00928
00929 if (view->rdclass == dns_rdataclass_in) {
00930 CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE,
00931 NULL, mctx));
00932 CHECK(load_view_keys(global_managed_keys, vconfig, view,
00933 ISC_TRUE, NULL, mctx));
00934 }
00935
00936
00937
00938
00939 obj = NULL;
00940 (void)ns_config_get(maps, "managed-keys-directory", &obj);
00941 directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL);
00942 if (directory != NULL)
00943 result = isc_file_isdirectory(directory);
00944 if (result != ISC_R_SUCCESS) {
00945 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
00946 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
00947 "invalid managed-keys-directory %s: %s",
00948 directory, isc_result_totext(result));
00949 goto cleanup;
00950
00951 }
00952 CHECK(add_keydata_zone(view, directory, ns_g_mctx));
00953
00954 cleanup:
00955 return (result);
00956 }
00957
00958 static isc_result_t
00959 mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
00960 const cfg_listelt_t *element;
00961 const cfg_obj_t *obj;
00962 const char *str;
00963 dns_fixedname_t fixed;
00964 dns_name_t *name;
00965 isc_boolean_t value;
00966 isc_result_t result;
00967 isc_buffer_t b;
00968
00969 dns_fixedname_init(&fixed);
00970 name = dns_fixedname_name(&fixed);
00971 for (element = cfg_list_first(mbs);
00972 element != NULL;
00973 element = cfg_list_next(element))
00974 {
00975 obj = cfg_listelt_value(element);
00976 str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
00977 isc_buffer_constinit(&b, str, strlen(str));
00978 isc_buffer_add(&b, strlen(str));
00979 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
00980 value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
00981 CHECK(dns_resolver_setmustbesecure(resolver, name, value));
00982 }
00983
00984 result = ISC_R_SUCCESS;
00985
00986 cleanup:
00987 return (result);
00988 }
00989
00990
00991
00992
00993 static isc_result_t
00994 get_view_querysource_dispatch(const cfg_obj_t **maps, int af,
00995 dns_dispatch_t **dispatchp, isc_dscp_t *dscpp,
00996 isc_boolean_t is_firstview)
00997 {
00998 isc_result_t result = ISC_R_FAILURE;
00999 dns_dispatch_t *disp;
01000 isc_sockaddr_t sa;
01001 unsigned int attrs, attrmask;
01002 const cfg_obj_t *obj = NULL;
01003 unsigned int maxdispatchbuffers = UDPBUFFERS;
01004 isc_dscp_t dscp = -1;
01005
01006 switch (af) {
01007 case AF_INET:
01008 result = ns_config_get(maps, "query-source", &obj);
01009 INSIST(result == ISC_R_SUCCESS);
01010 break;
01011 case AF_INET6:
01012 result = ns_config_get(maps, "query-source-v6", &obj);
01013 INSIST(result == ISC_R_SUCCESS);
01014 break;
01015 default:
01016 INSIST(0);
01017 }
01018
01019 sa = *(cfg_obj_assockaddr(obj));
01020 INSIST(isc_sockaddr_pf(&sa) == af);
01021
01022 dscp = cfg_obj_getdscp(obj);
01023 if (dscp != -1 && dscpp != NULL)
01024 *dscpp = dscp;
01025
01026
01027
01028
01029 switch (af) {
01030 case AF_INET:
01031 result = isc_net_probeipv4();
01032 break;
01033 case AF_INET6:
01034 result = isc_net_probeipv6();
01035 break;
01036 default:
01037 INSIST(0);
01038 }
01039 if (result != ISC_R_SUCCESS)
01040 return (ISC_R_SUCCESS);
01041
01042
01043
01044
01045 attrs = 0;
01046 attrs |= DNS_DISPATCHATTR_UDP;
01047 switch (af) {
01048 case AF_INET:
01049 attrs |= DNS_DISPATCHATTR_IPV4;
01050 break;
01051 case AF_INET6:
01052 attrs |= DNS_DISPATCHATTR_IPV6;
01053 break;
01054 }
01055 if (isc_sockaddr_getport(&sa) == 0) {
01056 attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
01057 maxdispatchbuffers = EXCLBUFFERS;
01058 } else {
01059 INSIST(obj != NULL);
01060 if (is_firstview) {
01061 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
01062 "using specific query-source port "
01063 "suppresses port randomization and can be "
01064 "insecure.");
01065 }
01066 }
01067
01068 attrmask = 0;
01069 attrmask |= DNS_DISPATCHATTR_UDP;
01070 attrmask |= DNS_DISPATCHATTR_TCP;
01071 attrmask |= DNS_DISPATCHATTR_IPV4;
01072 attrmask |= DNS_DISPATCHATTR_IPV6;
01073
01074 disp = NULL;
01075 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
01076 ns_g_taskmgr, &sa, 4096,
01077 maxdispatchbuffers, 32768, 16411, 16433,
01078 attrs, attrmask, &disp);
01079 if (result != ISC_R_SUCCESS) {
01080 isc_sockaddr_t any;
01081 char buf[ISC_SOCKADDR_FORMATSIZE];
01082
01083 switch (af) {
01084 case AF_INET:
01085 isc_sockaddr_any(&any);
01086 break;
01087 case AF_INET6:
01088 isc_sockaddr_any6(&any);
01089 break;
01090 }
01091 if (isc_sockaddr_equal(&sa, &any))
01092 return (ISC_R_SUCCESS);
01093 isc_sockaddr_format(&sa, buf, sizeof(buf));
01094 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
01095 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
01096 "could not get query source dispatcher (%s)",
01097 buf);
01098 return (result);
01099 }
01100
01101 *dispatchp = disp;
01102
01103 return (ISC_R_SUCCESS);
01104 }
01105
01106 static isc_result_t
01107 configure_order(dns_order_t *order, const cfg_obj_t *ent) {
01108 dns_rdataclass_t rdclass;
01109 dns_rdatatype_t rdtype;
01110 const cfg_obj_t *obj;
01111 dns_fixedname_t fixed;
01112 unsigned int mode = 0;
01113 const char *str;
01114 isc_buffer_t b;
01115 isc_result_t result;
01116 isc_boolean_t addroot;
01117
01118 result = ns_config_getclass(cfg_tuple_get(ent, "class"),
01119 dns_rdataclass_any, &rdclass);
01120 if (result != ISC_R_SUCCESS)
01121 return (result);
01122
01123 result = ns_config_gettype(cfg_tuple_get(ent, "type"),
01124 dns_rdatatype_any, &rdtype);
01125 if (result != ISC_R_SUCCESS)
01126 return (result);
01127
01128 obj = cfg_tuple_get(ent, "name");
01129 if (cfg_obj_isstring(obj))
01130 str = cfg_obj_asstring(obj);
01131 else
01132 str = "*";
01133 addroot = ISC_TF(strcmp(str, "*") == 0);
01134 isc_buffer_constinit(&b, str, strlen(str));
01135 isc_buffer_add(&b, strlen(str));
01136 dns_fixedname_init(&fixed);
01137 result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
01138 dns_rootname, 0, NULL);
01139 if (result != ISC_R_SUCCESS)
01140 return (result);
01141
01142 obj = cfg_tuple_get(ent, "ordering");
01143 INSIST(cfg_obj_isstring(obj));
01144 str = cfg_obj_asstring(obj);
01145 if (!strcasecmp(str, "fixed"))
01146 #if DNS_RDATASET_FIXED
01147 mode = DNS_RDATASETATTR_FIXEDORDER;
01148 #else
01149 mode = 0;
01150 #endif
01151 else if (!strcasecmp(str, "random"))
01152 mode = DNS_RDATASETATTR_RANDOMIZE;
01153 else if (!strcasecmp(str, "cyclic"))
01154 mode = 0;
01155 else
01156 INSIST(0);
01157
01158
01159
01160
01161
01162
01163 if (addroot) {
01164 result = dns_order_add(order, dns_rootname,
01165 rdtype, rdclass, mode);
01166 if (result != ISC_R_SUCCESS)
01167 return (result);
01168 }
01169
01170 return (dns_order_add(order, dns_fixedname_name(&fixed),
01171 rdtype, rdclass, mode));
01172 }
01173
01174 static isc_result_t
01175 configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
01176 isc_netaddr_t na;
01177 dns_peer_t *peer;
01178 const cfg_obj_t *obj;
01179 const char *str;
01180 isc_result_t result;
01181 unsigned int prefixlen;
01182
01183 cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
01184
01185 peer = NULL;
01186 result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
01187 if (result != ISC_R_SUCCESS)
01188 return (result);
01189
01190 obj = NULL;
01191 (void)cfg_map_get(cpeer, "bogus", &obj);
01192 if (obj != NULL)
01193 CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
01194
01195 obj = NULL;
01196 (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
01197 if (obj != NULL)
01198 CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
01199
01200 obj = NULL;
01201 (void)cfg_map_get(cpeer, "request-expire", &obj);
01202 if (obj != NULL)
01203 CHECK(dns_peer_setrequestexpire(peer, cfg_obj_asboolean(obj)));
01204
01205 obj = NULL;
01206 (void)cfg_map_get(cpeer, "request-ixfr", &obj);
01207 if (obj != NULL)
01208 CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
01209
01210 obj = NULL;
01211 (void)cfg_map_get(cpeer, "request-nsid", &obj);
01212 if (obj != NULL)
01213 CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
01214
01215 #ifdef ISC_PLATFORM_USESIT
01216 obj = NULL;
01217 (void)cfg_map_get(cpeer, "request-sit", &obj);
01218 if (obj != NULL)
01219 CHECK(dns_peer_setrequestsit(peer, cfg_obj_asboolean(obj)));
01220 #endif
01221
01222 obj = NULL;
01223 (void)cfg_map_get(cpeer, "edns", &obj);
01224 if (obj != NULL)
01225 CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
01226
01227 obj = NULL;
01228 (void)cfg_map_get(cpeer, "edns-udp-size", &obj);
01229 if (obj != NULL) {
01230 isc_uint32_t udpsize = cfg_obj_asuint32(obj);
01231 if (udpsize < 512)
01232 udpsize = 512;
01233 if (udpsize > 4096)
01234 udpsize = 4096;
01235 CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize));
01236 }
01237
01238 obj = NULL;
01239 (void)cfg_map_get(cpeer, "edns-version", &obj);
01240 if (obj != NULL) {
01241 isc_uint32_t ednsversion = cfg_obj_asuint32(obj);
01242 if (ednsversion > 255)
01243 ednsversion = 255;
01244 CHECK(dns_peer_setednsversion(peer, (isc_uint8_t)ednsversion));
01245 }
01246
01247 obj = NULL;
01248 (void)cfg_map_get(cpeer, "max-udp-size", &obj);
01249 if (obj != NULL) {
01250 isc_uint32_t udpsize = cfg_obj_asuint32(obj);
01251 if (udpsize < 512)
01252 udpsize = 512;
01253 if (udpsize > 4096)
01254 udpsize = 4096;
01255 CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize));
01256 }
01257
01258 obj = NULL;
01259 (void)cfg_map_get(cpeer, "tcp-only", &obj);
01260 if (obj != NULL)
01261 CHECK(dns_peer_setforcetcp(peer, cfg_obj_asboolean(obj)));
01262
01263 obj = NULL;
01264 (void)cfg_map_get(cpeer, "transfers", &obj);
01265 if (obj != NULL)
01266 CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
01267
01268 obj = NULL;
01269 (void)cfg_map_get(cpeer, "transfer-format", &obj);
01270 if (obj != NULL) {
01271 str = cfg_obj_asstring(obj);
01272 if (strcasecmp(str, "many-answers") == 0)
01273 CHECK(dns_peer_settransferformat(peer,
01274 dns_many_answers));
01275 else if (strcasecmp(str, "one-answer") == 0)
01276 CHECK(dns_peer_settransferformat(peer,
01277 dns_one_answer));
01278 else
01279 INSIST(0);
01280 }
01281
01282 obj = NULL;
01283 (void)cfg_map_get(cpeer, "keys", &obj);
01284 if (obj != NULL) {
01285 result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
01286 if (result != ISC_R_SUCCESS)
01287 goto cleanup;
01288 }
01289
01290 obj = NULL;
01291 if (na.family == AF_INET)
01292 (void)cfg_map_get(cpeer, "transfer-source", &obj);
01293 else
01294 (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
01295 if (obj != NULL) {
01296 result = dns_peer_settransfersource(peer,
01297 cfg_obj_assockaddr(obj));
01298 if (result != ISC_R_SUCCESS)
01299 goto cleanup;
01300 result = dns_peer_settransferdscp(peer, cfg_obj_getdscp(obj));
01301 if (result != ISC_R_SUCCESS)
01302 goto cleanup;
01303 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
01304 }
01305
01306 obj = NULL;
01307 if (na.family == AF_INET)
01308 (void)cfg_map_get(cpeer, "notify-source", &obj);
01309 else
01310 (void)cfg_map_get(cpeer, "notify-source-v6", &obj);
01311 if (obj != NULL) {
01312 result = dns_peer_setnotifysource(peer,
01313 cfg_obj_assockaddr(obj));
01314 if (result != ISC_R_SUCCESS)
01315 goto cleanup;
01316 result = dns_peer_setnotifydscp(peer, cfg_obj_getdscp(obj));
01317 if (result != ISC_R_SUCCESS)
01318 goto cleanup;
01319 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
01320 }
01321
01322 obj = NULL;
01323 if (na.family == AF_INET)
01324 (void)cfg_map_get(cpeer, "query-source", &obj);
01325 else
01326 (void)cfg_map_get(cpeer, "query-source-v6", &obj);
01327 if (obj != NULL) {
01328 result = dns_peer_setquerysource(peer,
01329 cfg_obj_assockaddr(obj));
01330 if (result != ISC_R_SUCCESS)
01331 goto cleanup;
01332 result = dns_peer_setquerydscp(peer, cfg_obj_getdscp(obj));
01333 if (result != ISC_R_SUCCESS)
01334 goto cleanup;
01335 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
01336 }
01337
01338 *peerp = peer;
01339 return (ISC_R_SUCCESS);
01340
01341 cleanup:
01342 dns_peer_detach(&peer);
01343 return (result);
01344 }
01345
01346 static isc_result_t
01347 disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
01348 isc_result_t result;
01349 const cfg_obj_t *algorithms;
01350 const cfg_listelt_t *element;
01351 const char *str;
01352 dns_fixedname_t fixed;
01353 dns_name_t *name;
01354 isc_buffer_t b;
01355
01356 dns_fixedname_init(&fixed);
01357 name = dns_fixedname_name(&fixed);
01358 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
01359 isc_buffer_constinit(&b, str, strlen(str));
01360 isc_buffer_add(&b, strlen(str));
01361 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
01362
01363 algorithms = cfg_tuple_get(disabled, "algorithms");
01364 for (element = cfg_list_first(algorithms);
01365 element != NULL;
01366 element = cfg_list_next(element))
01367 {
01368 isc_textregion_t r;
01369 dns_secalg_t alg;
01370
01371 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
01372 r.length = strlen(r.base);
01373
01374 result = dns_secalg_fromtext(&alg, &r);
01375 if (result != ISC_R_SUCCESS) {
01376 isc_uint8_t ui;
01377 result = isc_parse_uint8(&ui, r.base, 10);
01378 alg = ui;
01379 }
01380 if (result != ISC_R_SUCCESS) {
01381 cfg_obj_log(cfg_listelt_value(element),
01382 ns_g_lctx, ISC_LOG_ERROR,
01383 "invalid algorithm");
01384 CHECK(result);
01385 }
01386 CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
01387 }
01388 cleanup:
01389 return (result);
01390 }
01391
01392 static isc_result_t
01393 disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
01394 isc_result_t result;
01395 const cfg_obj_t *digests;
01396 const cfg_listelt_t *element;
01397 const char *str;
01398 dns_fixedname_t fixed;
01399 dns_name_t *name;
01400 isc_buffer_t b;
01401
01402 dns_fixedname_init(&fixed);
01403 name = dns_fixedname_name(&fixed);
01404 str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
01405 isc_buffer_constinit(&b, str, strlen(str));
01406 isc_buffer_add(&b, strlen(str));
01407 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
01408
01409 digests = cfg_tuple_get(disabled, "digests");
01410 for (element = cfg_list_first(digests);
01411 element != NULL;
01412 element = cfg_list_next(element))
01413 {
01414 isc_textregion_t r;
01415 dns_dsdigest_t digest;
01416
01417 DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
01418 r.length = strlen(r.base);
01419
01420
01421 result = dns_dsdigest_fromtext(&digest, &r);
01422 if (result != ISC_R_SUCCESS) {
01423 cfg_obj_log(cfg_listelt_value(element),
01424 ns_g_lctx, ISC_LOG_ERROR,
01425 "invalid algorithm");
01426 CHECK(result);
01427 }
01428 CHECK(dns_resolver_disable_ds_digest(resolver, name, digest));
01429 }
01430 cleanup:
01431 return (result);
01432 }
01433
01434 static isc_boolean_t
01435 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
01436 const cfg_listelt_t *element;
01437 dns_fixedname_t fixed;
01438 dns_name_t *name;
01439 isc_result_t result;
01440 const cfg_obj_t *value;
01441 const char *str;
01442 isc_buffer_t b;
01443
01444 dns_fixedname_init(&fixed);
01445 name = dns_fixedname_name(&fixed);
01446
01447 for (element = cfg_list_first(disablelist);
01448 element != NULL;
01449 element = cfg_list_next(element))
01450 {
01451 value = cfg_listelt_value(element);
01452 str = cfg_obj_asstring(value);
01453 isc_buffer_constinit(&b, str, strlen(str));
01454 isc_buffer_add(&b, strlen(str));
01455 result = dns_name_fromtext(name, &b, dns_rootname,
01456 0, NULL);
01457 RUNTIME_CHECK(result == ISC_R_SUCCESS);
01458 if (dns_name_equal(name, zonename))
01459 return (ISC_TRUE);
01460 }
01461 return (ISC_FALSE);
01462 }
01463
01464 static isc_result_t
01465 check_dbtype(dns_zone_t *zone, unsigned int dbtypec, const char **dbargv,
01466 isc_mem_t *mctx)
01467 {
01468 char **argv = NULL;
01469 unsigned int i;
01470 isc_result_t result = ISC_R_SUCCESS;
01471
01472 CHECK(dns_zone_getdbtype(zone, &argv, mctx));
01473
01474
01475
01476
01477 for (i = 0; i < dbtypec; i++)
01478 if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0)
01479 CHECK(ISC_R_FAILURE);
01480
01481
01482
01483
01484 if (i == dbtypec && argv[i] != NULL)
01485 result = ISC_R_FAILURE;
01486
01487 cleanup:
01488 isc_mem_free(mctx, argv);
01489 return (result);
01490 }
01491
01492 static isc_result_t
01493 setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) {
01494 isc_result_t result;
01495 isc_stats_t *zoneqrystats;
01496
01497 dns_zone_setstatlevel(zone, level);
01498
01499 zoneqrystats = NULL;
01500 if (level == dns_zonestat_full) {
01501 result = isc_stats_create(mctx, &zoneqrystats,
01502 dns_nsstatscounter_max);
01503 if (result != ISC_R_SUCCESS)
01504 return (result);
01505 }
01506 dns_zone_setrequeststats(zone, zoneqrystats);
01507 if (zoneqrystats != NULL)
01508 isc_stats_detach(&zoneqrystats);
01509
01510 return (ISC_R_SUCCESS);
01511 }
01512
01513 static ns_cache_t *
01514 cachelist_find(ns_cachelist_t *cachelist, const char *cachename) {
01515 ns_cache_t *nsc;
01516
01517 for (nsc = ISC_LIST_HEAD(*cachelist);
01518 nsc != NULL;
01519 nsc = ISC_LIST_NEXT(nsc, link)) {
01520 if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0)
01521 return (nsc);
01522 }
01523
01524 return (NULL);
01525 }
01526
01527 static isc_boolean_t
01528 cache_reusable(dns_view_t *originview, dns_view_t *view,
01529 isc_boolean_t new_zero_no_soattl)
01530 {
01531 if (originview->checknames != view->checknames ||
01532 dns_resolver_getzeronosoattl(originview->resolver) !=
01533 new_zero_no_soattl ||
01534 originview->acceptexpired != view->acceptexpired ||
01535 originview->enablevalidation != view->enablevalidation ||
01536 originview->maxcachettl != view->maxcachettl ||
01537 originview->maxncachettl != view->maxncachettl) {
01538 return (ISC_FALSE);
01539 }
01540
01541 return (ISC_TRUE);
01542 }
01543
01544 static isc_boolean_t
01545 cache_sharable(dns_view_t *originview, dns_view_t *view,
01546 isc_boolean_t new_zero_no_soattl,
01547 unsigned int new_cleaning_interval,
01548 isc_uint64_t new_max_cache_size)
01549 {
01550
01551
01552
01553
01554 if (!cache_reusable(originview, view, new_zero_no_soattl))
01555 return (ISC_FALSE);
01556
01557
01558
01559
01560
01561 if (dns_cache_getcleaninginterval(originview->cache) !=
01562 new_cleaning_interval ||
01563 dns_cache_getcachesize(originview->cache) != new_max_cache_size) {
01564 return (ISC_FALSE);
01565 }
01566
01567 return (ISC_TRUE);
01568 }
01569
01570
01571
01572
01573 static isc_result_t
01574 dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
01575 dns_name_t *origin = dns_zone_getorigin(zone);
01576 dns_rdataclass_t zclass = view->rdclass;
01577 isc_result_t result;
01578
01579 result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone);
01580 if (result != ISC_R_SUCCESS)
01581 return (result);
01582 dns_zone_setstats(zone, ns_g_server->zonestats);
01583
01584 return (ns_zone_configure_writeable_dlz(dlzdb, zone, zclass, origin));
01585 }
01586
01587 static isc_result_t
01588 dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
01589 unsigned int prefixlen, const char *server,
01590 const char *contact)
01591 {
01592 char *cp;
01593 char reverse[48+sizeof("ip6.arpa.")];
01594 const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." };
01595 const char *sep = ": view ";
01596 const char *viewname = view->name;
01597 const unsigned char *s6;
01598 dns_fixedname_t fixed;
01599 dns_name_t *name;
01600 dns_zone_t *zone = NULL;
01601 int dns64_dbtypec = 4;
01602 isc_buffer_t b;
01603 isc_result_t result;
01604
01605 REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
01606 prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
01607
01608 if (!strcmp(viewname, "_default")) {
01609 sep = "";
01610 viewname = "";
01611 }
01612
01613
01614
01615
01616 cp = reverse;
01617 s6 = na->type.in6.s6_addr;
01618 while (prefixlen > 0) {
01619 prefixlen -= 8;
01620 sprintf(cp, "%x.%x.", s6[prefixlen/8] & 0xf,
01621 (s6[prefixlen/8] >> 4) & 0xf);
01622 cp += 4;
01623 }
01624 strcat(cp, "ip6.arpa.");
01625
01626
01627
01628
01629 if (server != NULL)
01630 dns64_dbtype[2] = server;
01631 if (contact != NULL)
01632 dns64_dbtype[3] = contact;
01633 dns_fixedname_init(&fixed);
01634 name = dns_fixedname_name(&fixed);
01635 isc_buffer_constinit(&b, reverse, strlen(reverse));
01636 isc_buffer_add(&b, strlen(reverse));
01637 CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
01638 CHECK(dns_zone_create(&zone, mctx));
01639 CHECK(dns_zone_setorigin(zone, name));
01640 dns_zone_setview(zone, view);
01641 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
01642 dns_zone_setclass(zone, view->rdclass);
01643 dns_zone_settype(zone, dns_zone_master);
01644 dns_zone_setstats(zone, ns_g_server->zonestats);
01645 CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype));
01646 if (view->queryacl != NULL)
01647 dns_zone_setqueryacl(zone, view->queryacl);
01648 if (view->queryonacl != NULL)
01649 dns_zone_setqueryonacl(zone, view->queryonacl);
01650 dns_zone_setdialup(zone, dns_dialuptype_no);
01651 dns_zone_setnotifytype(zone, dns_notifytype_no);
01652 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
01653 CHECK(setquerystats(zone, mctx, dns_zonestat_none));
01654 CHECK(dns_view_addzone(view, zone));
01655 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
01656 ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep,
01657 viewname, reverse);
01658
01659 cleanup:
01660 if (zone != NULL)
01661 dns_zone_detach(&zone);
01662 return (result);
01663 }
01664
01665 static isc_result_t
01666 configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name,
01667 const char *str, const char *msg)
01668 {
01669 isc_result_t result;
01670
01671 result = dns_name_fromstring(name, str, DNS_NAME_DOWNCASE, view->mctx);
01672 if (result != ISC_R_SUCCESS)
01673 cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
01674 "invalid %s '%s'", msg, str);
01675 return (result);
01676 }
01677
01678 static isc_result_t
01679 configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name,
01680 const char *str, const dns_name_t *origin)
01681 {
01682 isc_result_t result;
01683
01684 result = dns_name_fromstring2(name, str, origin, DNS_NAME_DOWNCASE,
01685 view->mctx);
01686 if (result != ISC_R_SUCCESS)
01687 cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
01688 "invalid zone '%s'", str);
01689 return (result);
01690 }
01691
01692 static isc_result_t
01693 configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element,
01694 isc_boolean_t recursive_only_def, dns_ttl_t ttl_def,
01695 const dns_rpz_zone_t *old, isc_boolean_t *old_rpz_okp)
01696 {
01697 const cfg_obj_t *rpz_obj, *obj;
01698 const char *str;
01699 dns_rpz_zone_t *new;
01700 isc_result_t result;
01701 dns_rpz_num_t rpz_num;
01702
01703 REQUIRE(old != NULL || !*old_rpz_okp);
01704
01705 rpz_obj = cfg_listelt_value(element);
01706
01707 if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) {
01708 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
01709 "limit of %d response policy zones exceeded",
01710 DNS_RPZ_MAX_ZONES);
01711 return (ISC_R_FAILURE);
01712 }
01713
01714 new = isc_mem_get(view->rpzs->mctx, sizeof(*new));
01715 if (new == NULL) {
01716 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
01717 "no memory for response policy zones");
01718 return (ISC_R_NOMEMORY);
01719 }
01720
01721 memset(new, 0, sizeof(*new));
01722 result = isc_refcount_init(&new->refs, 1);
01723 if (result != ISC_R_SUCCESS) {
01724 isc_mem_put(view->rpzs->mctx, new, sizeof(*new));
01725 return (result);
01726 }
01727 dns_name_init(&new->origin, NULL);
01728 dns_name_init(&new->client_ip, NULL);
01729 dns_name_init(&new->ip, NULL);
01730 dns_name_init(&new->nsdname, NULL);
01731 dns_name_init(&new->nsip, NULL);
01732 dns_name_init(&new->passthru, NULL);
01733 dns_name_init(&new->drop, NULL);
01734 dns_name_init(&new->tcp_only, NULL);
01735 dns_name_init(&new->cname, NULL);
01736 new->num = view->rpzs->p.num_zones++;
01737 view->rpzs->zones[new->num] = new;
01738
01739 obj = cfg_tuple_get(rpz_obj, "recursive-only");
01740 if (cfg_obj_isvoid(obj) ? recursive_only_def : cfg_obj_asboolean(obj)) {
01741 view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(new->num);
01742 } else {
01743 view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(new->num);
01744 }
01745
01746 obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
01747 if (cfg_obj_isuint32(obj)) {
01748 new->max_policy_ttl = cfg_obj_asuint32(obj);
01749 } else {
01750 new->max_policy_ttl = ttl_def;
01751 }
01752 if (*old_rpz_okp && new->max_policy_ttl != old->max_policy_ttl)
01753 *old_rpz_okp = ISC_FALSE;
01754
01755 str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name"));
01756 result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone");
01757 if (result != ISC_R_SUCCESS)
01758 return (result);
01759 if (dns_name_equal(&new->origin, dns_rootname)) {
01760 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
01761 "invalid zone name '%s'", str);
01762 return (DNS_R_EMPTYLABEL);
01763 }
01764 for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones-1; ++rpz_num) {
01765 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin,
01766 &new->origin)) {
01767 cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
01768 "duplicate '%s'", str);
01769 result = DNS_R_DUPLICATE;
01770 return (result);
01771 }
01772 }
01773 if (*old_rpz_okp && !dns_name_equal(&old->origin, &new->origin))
01774 *old_rpz_okp = ISC_FALSE;
01775
01776 result = configure_rpz_name2(view, rpz_obj, &new->client_ip,
01777 DNS_RPZ_CLIENT_IP_ZONE, &new->origin);
01778 if (result != ISC_R_SUCCESS)
01779 return (result);
01780
01781 result = configure_rpz_name2(view, rpz_obj, &new->ip,
01782 DNS_RPZ_IP_ZONE, &new->origin);
01783 if (result != ISC_R_SUCCESS)
01784 return (result);
01785
01786 result = configure_rpz_name2(view, rpz_obj, &new->nsdname,
01787 DNS_RPZ_NSDNAME_ZONE, &new->origin);
01788 if (result != ISC_R_SUCCESS)
01789 return (result);
01790
01791 result = configure_rpz_name2(view, rpz_obj, &new->nsip,
01792 DNS_RPZ_NSIP_ZONE, &new->origin);
01793 if (result != ISC_R_SUCCESS)
01794 return (result);
01795
01796 result = configure_rpz_name(view, rpz_obj, &new->passthru,
01797 DNS_RPZ_PASSTHRU_NAME, "name");
01798 if (result != ISC_R_SUCCESS)
01799 return (result);
01800
01801 result = configure_rpz_name(view, rpz_obj, &new->drop,
01802 DNS_RPZ_DROP_NAME, "name");
01803 if (result != ISC_R_SUCCESS)
01804 return (result);
01805
01806 result = configure_rpz_name(view, rpz_obj, &new->tcp_only,
01807 DNS_RPZ_TCP_ONLY_NAME, "name");
01808 if (result != ISC_R_SUCCESS)
01809 return (result);
01810
01811 obj = cfg_tuple_get(rpz_obj, "policy");
01812 if (cfg_obj_isvoid(obj)) {
01813 new->policy = DNS_RPZ_POLICY_GIVEN;
01814 } else {
01815 str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name"));
01816 new->policy = dns_rpz_str2policy(str);
01817 INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
01818 if (new->policy == DNS_RPZ_POLICY_CNAME) {
01819 str = cfg_obj_asstring(cfg_tuple_get(obj, "cname"));
01820 result = configure_rpz_name(view, rpz_obj, &new->cname,
01821 str, "cname");
01822 if (result != ISC_R_SUCCESS)
01823 return (result);
01824 }
01825 }
01826 if (*old_rpz_okp && (new->policy != old->policy ||
01827 !dns_name_equal(&old->cname, &new->cname)))
01828 *old_rpz_okp = ISC_FALSE;
01829
01830 return (ISC_R_SUCCESS);
01831 }
01832
01833 static isc_result_t
01834 configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj,
01835 isc_boolean_t *old_rpz_okp)
01836 {
01837 const cfg_listelt_t *zone_element;
01838 const cfg_obj_t *sub_obj;
01839 isc_boolean_t recursive_only_def;
01840 dns_ttl_t ttl_def;
01841 dns_rpz_zones_t *new;
01842 const dns_rpz_zones_t *old;
01843 dns_view_t *pview;
01844 const dns_rpz_zone_t *old_zone;
01845 isc_result_t result;
01846 int i;
01847
01848 *old_rpz_okp = ISC_FALSE;
01849
01850 zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list"));
01851 if (zone_element == NULL)
01852 return (ISC_R_SUCCESS);
01853
01854 result = dns_rpz_new_zones(&view->rpzs, view->mctx);
01855 if (result != ISC_R_SUCCESS)
01856 return (result);
01857 new = view->rpzs;
01858
01859 sub_obj = cfg_tuple_get(rpz_obj, "recursive-only");
01860 if (!cfg_obj_isvoid(sub_obj) &&
01861 !cfg_obj_asboolean(sub_obj))
01862 recursive_only_def = ISC_FALSE;
01863 else
01864 recursive_only_def = ISC_TRUE;
01865
01866 sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec");
01867 if (!cfg_obj_isvoid(sub_obj) &&
01868 cfg_obj_asboolean(sub_obj))
01869 new->p.break_dnssec = ISC_TRUE;
01870 else
01871 new->p.break_dnssec = ISC_FALSE;
01872
01873 sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl");
01874 if (cfg_obj_isuint32(sub_obj))
01875 ttl_def = cfg_obj_asuint32(sub_obj);
01876 else
01877 ttl_def = DNS_RPZ_MAX_TTL_DEFAULT;
01878
01879 sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots");
01880 if (cfg_obj_isuint32(sub_obj))
01881 new->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1;
01882 else
01883 new->p.min_ns_labels = 2;
01884
01885 sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse");
01886 if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj))
01887 new->p.qname_wait_recurse = ISC_TRUE;
01888 else
01889 new->p.qname_wait_recurse = ISC_FALSE;
01890
01891 pview = NULL;
01892 result = dns_viewlist_find(&ns_g_server->viewlist,
01893 view->name, view->rdclass, &pview);
01894 if (result == ISC_R_SUCCESS) {
01895 old = pview->rpzs;
01896 } else {
01897 old = NULL;
01898 }
01899 if (old == NULL)
01900 *old_rpz_okp = ISC_FALSE;
01901 else
01902 *old_rpz_okp = ISC_TRUE;
01903
01904 for (i = 0;
01905 zone_element != NULL;
01906 ++i, zone_element = cfg_list_next(zone_element)) {
01907 INSIST(old != NULL || !*old_rpz_okp);
01908 if (*old_rpz_okp && i < old->p.num_zones) {
01909 old_zone = old->zones[i];
01910 } else {
01911 *old_rpz_okp = ISC_FALSE;
01912 old_zone = NULL;
01913 }
01914 result = configure_rpz_zone(view, zone_element,
01915 recursive_only_def, ttl_def,
01916 old_zone, old_rpz_okp);
01917 if (result != ISC_R_SUCCESS) {
01918 if (pview != NULL)
01919 dns_view_detach(&pview);
01920 return (result);
01921 }
01922 }
01923
01924
01925
01926
01927
01928
01929 if (old != NULL && memcmp(&old->p, &new->p, sizeof(new->p)) != 0)
01930 *old_rpz_okp = ISC_FALSE;
01931 if (*old_rpz_okp) {
01932 dns_rpz_detach_rpzs(&view->rpzs);
01933 dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs);
01934 }
01935 if (pview != NULL)
01936 dns_view_detach(&pview);
01937
01938 return (ISC_R_SUCCESS);
01939 }
01940
01941 #define CHECK_RRL(cond, pat, val1, val2) \
01942 do { \
01943 if (!(cond)) { \
01944 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, \
01945 pat, val1, val2); \
01946 result = ISC_R_RANGE; \
01947 goto cleanup; \
01948 } \
01949 } while (0)
01950
01951 #define CHECK_RRL_RATE(rate, def, max_rate, name) \
01952 do { \
01953 obj = NULL; \
01954 rrl->rate.str = name; \
01955 result = cfg_map_get(map, name, &obj); \
01956 if (result == ISC_R_SUCCESS) { \
01957 rrl->rate.r = cfg_obj_asuint32(obj); \
01958 CHECK_RRL(rrl->rate.r <= max_rate, \
01959 name" %d > %d", \
01960 rrl->rate.r, max_rate); \
01961 } else { \
01962 rrl->rate.r = def; \
01963 } \
01964 rrl->rate.scaled = rrl->rate.r; \
01965 } while (0)
01966
01967 static isc_result_t
01968 configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) {
01969 const cfg_obj_t *obj;
01970 dns_rrl_t *rrl;
01971 isc_result_t result;
01972 int min_entries, i, j;
01973
01974
01975
01976
01977
01978
01979
01980 min_entries = 500;
01981 obj = NULL;
01982 result = cfg_map_get(map, "min-table-size", &obj);
01983 if (result == ISC_R_SUCCESS) {
01984 min_entries = cfg_obj_asuint32(obj);
01985 if (min_entries < 1)
01986 min_entries = 1;
01987 }
01988 result = dns_rrl_init(&rrl, view, min_entries);
01989 if (result != ISC_R_SUCCESS)
01990 return (result);
01991
01992 i = ISC_MAX(20000, min_entries);
01993 obj = NULL;
01994 result = cfg_map_get(map, "max-table-size", &obj);
01995 if (result == ISC_R_SUCCESS) {
01996 i = cfg_obj_asuint32(obj);
01997 CHECK_RRL(i >= min_entries,
01998 "max-table-size %d < min-table-size %d",
01999 i, min_entries);
02000 }
02001 rrl->max_entries = i;
02002
02003 CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE,
02004 "responses-per-second");
02005 CHECK_RRL_RATE(referrals_per_second,
02006 rrl->responses_per_second.r, DNS_RRL_MAX_RATE,
02007 "referrals-per-second");
02008 CHECK_RRL_RATE(nodata_per_second,
02009 rrl->responses_per_second.r, DNS_RRL_MAX_RATE,
02010 "nodata-per-second");
02011 CHECK_RRL_RATE(nxdomains_per_second,
02012 rrl->responses_per_second.r, DNS_RRL_MAX_RATE,
02013 "nxdomains-per-second");
02014 CHECK_RRL_RATE(errors_per_second,
02015 rrl->responses_per_second.r, DNS_RRL_MAX_RATE,
02016 "errors-per-second");
02017
02018 CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE,
02019 "all-per-second");
02020
02021 CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP,
02022 "slip");
02023
02024 i = 15;
02025 obj = NULL;
02026 result = cfg_map_get(map, "window", &obj);
02027 if (result == ISC_R_SUCCESS) {
02028 i = cfg_obj_asuint32(obj);
02029 CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW,
02030 "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW);
02031 }
02032 rrl->window = i;
02033
02034 i = 0;
02035 obj = NULL;
02036 result = cfg_map_get(map, "qps-scale", &obj);
02037 if (result == ISC_R_SUCCESS) {
02038 i = cfg_obj_asuint32(obj);
02039 CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, "");
02040 }
02041 rrl->qps_scale = i;
02042 rrl->qps = 1.0;
02043
02044 i = 24;
02045 obj = NULL;
02046 result = cfg_map_get(map, "ipv4-prefix-length", &obj);
02047 if (result == ISC_R_SUCCESS) {
02048 i = cfg_obj_asuint32(obj);
02049 CHECK_RRL(i >= 8 && i <= 32,
02050 "invalid 'ipv4-prefix-length %d'%s", i, "");
02051 }
02052 rrl->ipv4_prefixlen = i;
02053 if (i == 32)
02054 rrl->ipv4_mask = 0xffffffff;
02055 else
02056 rrl->ipv4_mask = htonl(0xffffffff << (32-i));
02057
02058 i = 56;
02059 obj = NULL;
02060 result = cfg_map_get(map, "ipv6-prefix-length", &obj);
02061 if (result == ISC_R_SUCCESS) {
02062 i = cfg_obj_asuint32(obj);
02063 CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX,
02064 "ipv6-prefix-length %d < 16 or > %d",
02065 i, DNS_RRL_MAX_PREFIX);
02066 }
02067 rrl->ipv6_prefixlen = i;
02068 for (j = 0; j < 4; ++j) {
02069 if (i <= 0) {
02070 rrl->ipv6_mask[j] = 0;
02071 } else if (i < 32) {
02072 rrl->ipv6_mask[j] = htonl(0xffffffff << (32-i));
02073 } else {
02074 rrl->ipv6_mask[j] = 0xffffffff;
02075 }
02076 i -= 32;
02077 }
02078
02079 obj = NULL;
02080 result = cfg_map_get(map, "exempt-clients", &obj);
02081 if (result == ISC_R_SUCCESS) {
02082 result = cfg_acl_fromconfig(obj, config, ns_g_lctx,
02083 ns_g_aclconfctx, ns_g_mctx,
02084 0, &rrl->exempt);
02085 CHECK_RRL(result == ISC_R_SUCCESS,
02086 "invalid %s%s", "address match list", "");
02087 }
02088
02089 obj = NULL;
02090 result = cfg_map_get(map, "log-only", &obj);
02091 if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj))
02092 rrl->log_only = ISC_TRUE;
02093 else
02094 rrl->log_only = ISC_FALSE;
02095
02096 return (ISC_R_SUCCESS);
02097
02098 cleanup:
02099 dns_rrl_view_destroy(view);
02100 return (result);
02101 }
02102
02103 static isc_result_t
02104 add_soa(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
02105 dns_name_t *origin, dns_name_t *contact)
02106 {
02107 dns_dbnode_t *node = NULL;
02108 dns_rdata_t rdata = DNS_RDATA_INIT;
02109 dns_rdatalist_t rdatalist;
02110 dns_rdataset_t rdataset;
02111 isc_result_t result;
02112 unsigned char buf[DNS_SOA_BUFFERSIZE];
02113
02114 CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db),
02115 0, 28800, 7200, 604800, 86400, buf, &rdata));
02116
02117 dns_rdatalist_init(&rdatalist);
02118 rdatalist.type = rdata.type;
02119 rdatalist.rdclass = rdata.rdclass;
02120 rdatalist.ttl = 86400;
02121 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
02122
02123 dns_rdataset_init(&rdataset);
02124 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
02125 CHECK(dns_db_findnode(db, name, ISC_TRUE, &node));
02126 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
02127
02128 cleanup:
02129 if (node != NULL)
02130 dns_db_detachnode(db, &node);
02131 return (result);
02132 }
02133
02134 static isc_result_t
02135 add_ns(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
02136 dns_name_t *nsname)
02137 {
02138 dns_dbnode_t *node = NULL;
02139 dns_rdata_ns_t ns;
02140 dns_rdata_t rdata = DNS_RDATA_INIT;
02141 dns_rdatalist_t rdatalist;
02142 dns_rdataset_t rdataset;
02143 isc_result_t result;
02144 isc_buffer_t b;
02145 unsigned char buf[DNS_NAME_MAXWIRE];
02146
02147 isc_buffer_init(&b, buf, sizeof(buf));
02148
02149 ns.common.rdtype = dns_rdatatype_ns;
02150 ns.common.rdclass = dns_db_class(db);
02151 ns.mctx = NULL;
02152 dns_name_init(&ns.name, NULL);
02153 dns_name_clone(nsname, &ns.name);
02154 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns,
02155 &ns, &b));
02156
02157 dns_rdatalist_init(&rdatalist);
02158 rdatalist.type = rdata.type;
02159 rdatalist.rdclass = rdata.rdclass;
02160 rdatalist.ttl = 86400;
02161 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
02162
02163 dns_rdataset_init(&rdataset);
02164 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
02165 CHECK(dns_db_findnode(db, name, ISC_TRUE, &node));
02166 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL));
02167
02168 cleanup:
02169 if (node != NULL)
02170 dns_db_detachnode(db, &node);
02171 return (result);
02172 }
02173
02174 static isc_result_t
02175 create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
02176 const cfg_obj_t *zonelist, const char **empty_dbtype,
02177 int empty_dbtypec, dns_zonestat_level_t statlevel)
02178 {
02179 char namebuf[DNS_NAME_FORMATSIZE];
02180 const cfg_listelt_t *element;
02181 const cfg_obj_t *obj;
02182 const cfg_obj_t *zconfig;
02183 const cfg_obj_t *zoptions;
02184 const char *rbt_dbtype[4] = { "rbt" };
02185 const char *sep = ": view ";
02186 const char *str;
02187 const char *viewname = view->name;
02188 dns_db_t *db = NULL;
02189 dns_dbversion_t *version = NULL;
02190 dns_fixedname_t cfixed;
02191 dns_fixedname_t fixed;
02192 dns_fixedname_t nsfixed;
02193 dns_name_t *contact;
02194 dns_name_t *ns;
02195 dns_name_t *zname;
02196 dns_zone_t *myzone = NULL;
02197 int rbt_dbtypec = 1;
02198 isc_result_t result;
02199 dns_namereln_t namereln;
02200 int order;
02201 unsigned int nlabels;
02202
02203 dns_fixedname_init(&fixed);
02204 zname = dns_fixedname_name(&fixed);
02205 dns_fixedname_init(&nsfixed);
02206 ns = dns_fixedname_name(&nsfixed);
02207 dns_fixedname_init(&cfixed);
02208 contact = dns_fixedname_name(&cfixed);
02209
02210
02211
02212
02213
02214 for (element = cfg_list_first(zonelist);
02215 element != NULL;
02216 element = cfg_list_next(element)) {
02217
02218 zconfig = cfg_listelt_value(element);
02219 str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
02220 CHECK(dns_name_fromstring(zname, str, 0, NULL));
02221 namereln = dns_name_fullcompare(zname, name, &order, &nlabels);
02222 if (namereln != dns_namereln_subdomain)
02223 continue;
02224
02225 zoptions = cfg_tuple_get(zconfig, "options");
02226
02227 obj = NULL;
02228 (void)cfg_map_get(zoptions, "type", &obj);
02229 if (obj != NULL &&
02230 strcasecmp(cfg_obj_asstring(obj), "forward") == 0) {
02231 obj = NULL;
02232 (void)cfg_map_get(zoptions, "forward", &obj);
02233 if (obj == NULL)
02234 continue;
02235 if (strcasecmp(cfg_obj_asstring(obj), "only") != 0)
02236 continue;
02237 }
02238 if (db == NULL) {
02239 CHECK(dns_db_create(view->mctx, "rbt", name,
02240 dns_dbtype_zone, view->rdclass,
02241 0, NULL, &db));
02242 CHECK(dns_db_newversion(db, &version));
02243 if (strcmp(empty_dbtype[2], "@") == 0)
02244 dns_name_clone(name, ns);
02245 else
02246 CHECK(dns_name_fromstring(ns, empty_dbtype[2],
02247 0, NULL));
02248 CHECK(dns_name_fromstring(contact, empty_dbtype[3],
02249 0, NULL));
02250 CHECK(add_soa(db, version, name, ns, contact));
02251 CHECK(add_ns(db, version, name, ns));
02252 }
02253 CHECK(add_ns(db, version, zname, dns_rootname));
02254 }
02255
02256
02257
02258
02259 if (zone != NULL) {
02260 unsigned int typec;
02261 const char **dbargv;
02262
02263 if (db != NULL) {
02264 typec = rbt_dbtypec;
02265 dbargv = rbt_dbtype;
02266 } else {
02267 typec = empty_dbtypec;
02268 dbargv = empty_dbtype;
02269 }
02270
02271 result = check_dbtype(zone, typec, dbargv, view->mctx);
02272 if (result != ISC_R_SUCCESS)
02273 zone = NULL;
02274
02275 if (zone != NULL && dns_zone_gettype(zone) != dns_zone_master)
02276 zone = NULL;
02277 if (zone != NULL && dns_zone_getfile(zone) != NULL)
02278 zone = NULL;
02279 if (zone != NULL) {
02280 dns_zone_getraw(zone, &myzone);
02281 if (myzone != NULL) {
02282 dns_zone_detach(&myzone);
02283 zone = NULL;
02284 }
02285 }
02286 }
02287
02288 if (zone == NULL) {
02289 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &myzone));
02290 zone = myzone;
02291 CHECK(dns_zone_setorigin(zone, name));
02292 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
02293 if (db == NULL)
02294 CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
02295 empty_dbtype));
02296 dns_zone_setclass(zone, view->rdclass);
02297 dns_zone_settype(zone, dns_zone_master);
02298 dns_zone_setstats(zone, ns_g_server->zonestats);
02299 }
02300
02301 dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, ISC_FALSE);
02302 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
02303 dns_zone_setnotifytype(zone, dns_notifytype_no);
02304 dns_zone_setdialup(zone, dns_dialuptype_no);
02305 dns_zone_setautomatic(zone, ISC_TRUE);
02306 if (view->queryacl != NULL)
02307 dns_zone_setqueryacl(zone, view->queryacl);
02308 else
02309 dns_zone_clearqueryacl(zone);
02310 if (view->queryonacl != NULL)
02311 dns_zone_setqueryonacl(zone, view->queryonacl);
02312 else
02313 dns_zone_clearqueryonacl(zone);
02314 dns_zone_clearupdateacl(zone);
02315 if (view->transferacl != NULL)
02316 dns_zone_setxfracl(zone, view->transferacl);
02317 else
02318 dns_zone_clearxfracl(zone);
02319
02320 CHECK(setquerystats(zone, view->mctx, statlevel));
02321 if (db != NULL) {
02322 dns_db_closeversion(db, &version, ISC_TRUE);
02323 CHECK(dns_zone_replacedb(zone, db, ISC_FALSE));
02324 }
02325 dns_zone_setview(zone, view);
02326 CHECK(dns_view_addzone(view, zone));
02327
02328 if (!strcmp(viewname, "_default")) {
02329 sep = "";
02330 viewname = "";
02331 }
02332 dns_name_format(name, namebuf, sizeof(namebuf));
02333 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
02334 ISC_LOG_INFO, "automatic empty zone%s%s: %s",
02335 sep, viewname, namebuf);
02336
02337 cleanup:
02338 if (myzone != NULL)
02339 dns_zone_detach(&myzone);
02340 if (version != NULL)
02341 dns_db_closeversion(db, &version, ISC_FALSE);
02342 if (db != NULL)
02343 dns_db_detach(&db);
02344
02345 INSIST(version == NULL);
02346
02347 return (result);
02348 }
02349
02350
02351
02352
02353
02354
02355
02356
02357 static isc_result_t
02358 configure_view(dns_view_t *view, dns_viewlist_t *viewlist,
02359 cfg_obj_t *config, cfg_obj_t *vconfig,
02360 ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys,
02361 isc_mem_t *mctx, cfg_aclconfctx_t *actx,
02362 isc_boolean_t need_hints)
02363 {
02364 const cfg_obj_t *maps[4];
02365 const cfg_obj_t *cfgmaps[3];
02366 const cfg_obj_t *optionmaps[3];
02367 const cfg_obj_t *options = NULL;
02368 const cfg_obj_t *voptions = NULL;
02369 const cfg_obj_t *forwardtype;
02370 const cfg_obj_t *forwarders;
02371 const cfg_obj_t *alternates;
02372 const cfg_obj_t *zonelist;
02373 const cfg_obj_t *dlzlist;
02374 const cfg_obj_t *dlz;
02375 unsigned int dlzargc;
02376 char **dlzargv;
02377 const cfg_obj_t *disabled;
02378 const cfg_obj_t *obj;
02379 const cfg_listelt_t *element;
02380 in_port_t port;
02381 dns_cache_t *cache = NULL;
02382 isc_result_t result;
02383 unsigned int cleaning_interval;
02384 size_t max_cache_size;
02385 size_t max_acache_size;
02386 size_t max_adb_size;
02387 isc_uint32_t lame_ttl, fail_ttl;
02388 dns_tsig_keyring_t *ring = NULL;
02389 dns_view_t *pview = NULL;
02390 isc_mem_t *cmctx = NULL, *hmctx = NULL;
02391 dns_dispatch_t *dispatch4 = NULL;
02392 dns_dispatch_t *dispatch6 = NULL;
02393 isc_boolean_t reused_cache = ISC_FALSE;
02394 isc_boolean_t shared_cache = ISC_FALSE;
02395 int i = 0, j = 0, k = 0;
02396 const char *str;
02397 const char *cachename = NULL;
02398 dns_order_t *order = NULL;
02399 isc_uint32_t udpsize;
02400 isc_uint32_t maxbits;
02401 unsigned int resopts = 0;
02402 dns_zone_t *zone = NULL;
02403 isc_uint32_t max_clients_per_query;
02404 isc_boolean_t empty_zones_enable;
02405 const cfg_obj_t *disablelist = NULL;
02406 isc_stats_t *resstats = NULL;
02407 dns_stats_t *resquerystats = NULL;
02408 isc_boolean_t auto_dlv = ISC_FALSE;
02409 isc_boolean_t auto_root = ISC_FALSE;
02410 ns_cache_t *nsc;
02411 isc_boolean_t zero_no_soattl;
02412 dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
02413 unsigned int query_timeout, ndisp;
02414 ns_cfgctx_t *nzctx;
02415 isc_boolean_t old_rpz_ok = ISC_FALSE;
02416 isc_dscp_t dscp4 = -1, dscp6 = -1;
02417
02418 REQUIRE(DNS_VIEW_VALID(view));
02419
02420 if (config != NULL)
02421 (void)cfg_map_get(config, "options", &options);
02422
02423
02424
02425
02426
02427
02428 if (vconfig != NULL) {
02429 voptions = cfg_tuple_get(vconfig, "options");
02430 maps[i++] = voptions;
02431 optionmaps[j++] = voptions;
02432 cfgmaps[k++] = voptions;
02433 }
02434 if (options != NULL) {
02435 maps[i++] = options;
02436 optionmaps[j++] = options;
02437 }
02438
02439 maps[i++] = ns_g_defaults;
02440 maps[i] = NULL;
02441 optionmaps[j] = NULL;
02442 if (config != NULL)
02443 cfgmaps[k++] = config;
02444 cfgmaps[k] = NULL;
02445
02446
02447
02448
02449 CHECKM(ns_config_getport(config, &port), "port");
02450 dns_view_setdstport(view, port);
02451
02452
02453
02454
02455
02456
02457 obj = NULL;
02458 (void)ns_config_get(maps, "acache-enable", &obj);
02459 if (obj != NULL && cfg_obj_asboolean(obj)) {
02460 cmctx = NULL;
02461 CHECK(isc_mem_create(0, 0, &cmctx));
02462 CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
02463 ns_g_timermgr));
02464 isc_mem_setname(cmctx, "acache", NULL);
02465 isc_mem_detach(&cmctx);
02466 }
02467 if (view->acache != NULL) {
02468 obj = NULL;
02469 result = ns_config_get(maps, "acache-cleaning-interval", &obj);
02470 INSIST(result == ISC_R_SUCCESS);
02471 dns_acache_setcleaninginterval(view->acache,
02472 cfg_obj_asuint32(obj) * 60);
02473
02474 obj = NULL;
02475 result = ns_config_get(maps, "max-acache-size", &obj);
02476 INSIST(result == ISC_R_SUCCESS);
02477 if (cfg_obj_isstring(obj)) {
02478 str = cfg_obj_asstring(obj);
02479 INSIST(strcasecmp(str, "unlimited") == 0);
02480 max_acache_size = 0;
02481 } else {
02482 isc_resourcevalue_t value;
02483 value = cfg_obj_asuint64(obj);
02484 if (value > SIZE_MAX) {
02485 cfg_obj_log(obj, ns_g_lctx,
02486 ISC_LOG_WARNING,
02487 "'max-acache-size "
02488 "%" ISC_PRINT_QUADFORMAT "u' "
02489 "is too large for this "
02490 "system; reducing to %lu",
02491 value, (unsigned long)SIZE_MAX);
02492 value = SIZE_MAX;
02493 }
02494 max_acache_size = (size_t) value;
02495 }
02496 dns_acache_setcachesize(view->acache, max_acache_size);
02497 }
02498
02499 CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx,
02500 ns_g_mctx, &view->queryacl));
02501 if (view->queryacl == NULL) {
02502 CHECK(configure_view_acl(NULL, ns_g_config, "allow-query",
02503 NULL, actx, ns_g_mctx,
02504 &view->queryacl));
02505 }
02506
02507
02508
02509
02510
02511 obj = NULL;
02512 if (view->rdclass == dns_rdataclass_in && need_hints &&
02513 ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) {
02514 CHECK(configure_rpz(view, obj, &old_rpz_ok));
02515 }
02516
02517
02518
02519
02520 zonelist = NULL;
02521 if (voptions != NULL)
02522 (void)cfg_map_get(voptions, "zone", &zonelist);
02523 else
02524 (void)cfg_map_get(config, "zone", &zonelist);
02525
02526
02527
02528
02529 for (element = cfg_list_first(zonelist);
02530 element != NULL;
02531 element = cfg_list_next(element))
02532 {
02533 const cfg_obj_t *zconfig = cfg_listelt_value(element);
02534 CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
02535 viewlist, actx, ISC_FALSE, old_rpz_ok,
02536 ISC_FALSE));
02537 }
02538
02539
02540
02541
02542
02543 if (view->rpzs != NULL) {
02544 dns_rpz_num_t n;
02545
02546 for (n = 0; n < view->rpzs->p.num_zones; ++n)
02547 {
02548 if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) {
02549 char namebuf[DNS_NAME_FORMATSIZE];
02550
02551 dns_name_format(&view->rpzs->zones[n]->origin,
02552 namebuf, sizeof(namebuf));
02553 cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
02554 "'%s' is not a master or slave zone",
02555 namebuf);
02556 result = ISC_R_NOTFOUND;
02557 goto cleanup;
02558 }
02559 }
02560 }
02561
02562
02563
02564
02565
02566
02567 nzctx = view->new_zone_config;
02568 if (nzctx != NULL && nzctx->nzconfig != NULL) {
02569 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
02570 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
02571 "loading additional zones for view '%s'",
02572 view->name);
02573
02574 zonelist = NULL;
02575 cfg_map_get(nzctx->nzconfig, "zone", &zonelist);
02576
02577 for (element = cfg_list_first(zonelist);
02578 element != NULL;
02579 element = cfg_list_next(element))
02580 {
02581 const cfg_obj_t *zconfig = cfg_listelt_value(element);
02582 CHECK(configure_zone(config, zconfig, vconfig,
02583 mctx, view, NULL, actx,
02584 ISC_TRUE, ISC_FALSE, ISC_FALSE));
02585 }
02586 }
02587
02588
02589
02590
02591 dlzlist = NULL;
02592 if (voptions != NULL)
02593 (void)cfg_map_get(voptions, "dlz", &dlzlist);
02594 else
02595 (void)cfg_map_get(config, "dlz", &dlzlist);
02596
02597 for (element = cfg_list_first(dlzlist);
02598 element != NULL;
02599 element = cfg_list_next(element))
02600 {
02601 dlz = cfg_listelt_value(element);
02602
02603 obj = NULL;
02604 (void)cfg_map_get(dlz, "database", &obj);
02605 if (obj != NULL) {
02606 dns_dlzdb_t *dlzdb = NULL;
02607 const cfg_obj_t *name, *search = NULL;
02608 char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
02609
02610 if (s == NULL) {
02611 result = ISC_R_NOMEMORY;
02612 goto cleanup;
02613 }
02614
02615 result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
02616 if (result != ISC_R_SUCCESS) {
02617 isc_mem_free(mctx, s);
02618 goto cleanup;
02619 }
02620
02621 name = cfg_map_getname(dlz);
02622 result = dns_dlzcreate(mctx, cfg_obj_asstring(name),
02623 dlzargv[0], dlzargc, dlzargv,
02624 &dlzdb);
02625 isc_mem_free(mctx, s);
02626 isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
02627 if (result != ISC_R_SUCCESS)
02628 goto cleanup;
02629
02630
02631
02632
02633
02634
02635
02636 (void)cfg_map_get(dlz, "search", &search);
02637 if (search == NULL || cfg_obj_asboolean(search)) {
02638 dlzdb->search = ISC_TRUE;
02639 result = dns_dlzconfigure(view, dlzdb,
02640 dlzconfigure_callback);
02641 if (result != ISC_R_SUCCESS)
02642 goto cleanup;
02643 ISC_LIST_APPEND(view->dlz_searched,
02644 dlzdb, link);
02645 } else {
02646 dlzdb->search = ISC_FALSE;
02647 ISC_LIST_APPEND(view->dlz_unsearched,
02648 dlzdb, link);
02649 }
02650
02651 }
02652 }
02653
02654
02655
02656
02657
02658 obj = NULL;
02659 result = ns_config_get(maps, "cleaning-interval", &obj);
02660 INSIST(result == ISC_R_SUCCESS);
02661 cleaning_interval = cfg_obj_asuint32(obj) * 60;
02662
02663 obj = NULL;
02664 result = ns_config_get(maps, "max-cache-size", &obj);
02665 INSIST(result == ISC_R_SUCCESS);
02666 if (cfg_obj_isstring(obj)) {
02667 str = cfg_obj_asstring(obj);
02668 INSIST(strcasecmp(str, "unlimited") == 0);
02669 max_cache_size = 0;
02670 } else {
02671 isc_resourcevalue_t value;
02672 value = cfg_obj_asuint64(obj);
02673 if (value > SIZE_MAX) {
02674 cfg_obj_log(obj, ns_g_lctx,
02675 ISC_LOG_WARNING,
02676 "'max-cache-size "
02677 "%" ISC_PRINT_QUADFORMAT "u' "
02678 "is too large for this "
02679 "system; reducing to %lu",
02680 value, (unsigned long)SIZE_MAX);
02681 value = SIZE_MAX;
02682 }
02683 max_cache_size = (size_t) value;
02684 }
02685
02686
02687 obj = NULL;
02688 result = ns_checknames_get(maps, "response", &obj);
02689 INSIST(result == ISC_R_SUCCESS);
02690
02691 str = cfg_obj_asstring(obj);
02692 if (strcasecmp(str, "fail") == 0) {
02693 resopts |= DNS_RESOLVER_CHECKNAMES |
02694 DNS_RESOLVER_CHECKNAMESFAIL;
02695 view->checknames = ISC_TRUE;
02696 } else if (strcasecmp(str, "warn") == 0) {
02697 resopts |= DNS_RESOLVER_CHECKNAMES;
02698 view->checknames = ISC_FALSE;
02699 } else if (strcasecmp(str, "ignore") == 0) {
02700 view->checknames = ISC_FALSE;
02701 } else
02702 INSIST(0);
02703
02704 obj = NULL;
02705 result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
02706 INSIST(result == ISC_R_SUCCESS);
02707 zero_no_soattl = cfg_obj_asboolean(obj);
02708
02709 obj = NULL;
02710 result = ns_config_get(maps, "dns64", &obj);
02711 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") &&
02712 strcmp(view->name, "_meta")) {
02713 isc_netaddr_t na, suffix, *sp;
02714 unsigned int prefixlen;
02715 const char *server, *contact;
02716 const cfg_obj_t *myobj;
02717
02718 myobj = NULL;
02719 result = ns_config_get(maps, "dns64-server", &myobj);
02720 if (result == ISC_R_SUCCESS)
02721 server = cfg_obj_asstring(myobj);
02722 else
02723 server = NULL;
02724
02725 myobj = NULL;
02726 result = ns_config_get(maps, "dns64-contact", &myobj);
02727 if (result == ISC_R_SUCCESS)
02728 contact = cfg_obj_asstring(myobj);
02729 else
02730 contact = NULL;
02731
02732 for (element = cfg_list_first(obj);
02733 element != NULL;
02734 element = cfg_list_next(element))
02735 {
02736 const cfg_obj_t *map = cfg_listelt_value(element);
02737 dns_dns64_t *dns64 = NULL;
02738 unsigned int dns64options = 0;
02739
02740 cfg_obj_asnetprefix(cfg_map_getname(map), &na,
02741 &prefixlen);
02742
02743 obj = NULL;
02744 (void)cfg_map_get(map, "suffix", &obj);
02745 if (obj != NULL) {
02746 sp = &suffix;
02747 isc_netaddr_fromsockaddr(sp,
02748 cfg_obj_assockaddr(obj));
02749 } else
02750 sp = NULL;
02751
02752 clients = mapped = excluded = NULL;
02753 obj = NULL;
02754 (void)cfg_map_get(map, "clients", &obj);
02755 if (obj != NULL) {
02756 result = cfg_acl_fromconfig(obj, config,
02757 ns_g_lctx, actx,
02758 mctx, 0, &clients);
02759 if (result != ISC_R_SUCCESS)
02760 goto cleanup;
02761 }
02762 obj = NULL;
02763 (void)cfg_map_get(map, "mapped", &obj);
02764 if (obj != NULL) {
02765 result = cfg_acl_fromconfig(obj, config,
02766 ns_g_lctx, actx,
02767 mctx, 0, &mapped);
02768 if (result != ISC_R_SUCCESS)
02769 goto cleanup;
02770 }
02771 obj = NULL;
02772 (void)cfg_map_get(map, "exclude", &obj);
02773 if (obj != NULL) {
02774 result = cfg_acl_fromconfig(obj, config,
02775 ns_g_lctx, actx,
02776 mctx, 0, &excluded);
02777 if (result != ISC_R_SUCCESS)
02778 goto cleanup;
02779 }
02780
02781 obj = NULL;
02782 (void)cfg_map_get(map, "recursive-only", &obj);
02783 if (obj != NULL && cfg_obj_asboolean(obj))
02784 dns64options |= DNS_DNS64_RECURSIVE_ONLY;
02785
02786 obj = NULL;
02787 (void)cfg_map_get(map, "break-dnssec", &obj);
02788 if (obj != NULL && cfg_obj_asboolean(obj))
02789 dns64options |= DNS_DNS64_BREAK_DNSSEC;
02790
02791 result = dns_dns64_create(mctx, &na, prefixlen, sp,
02792 clients, mapped, excluded,
02793 dns64options, &dns64);
02794 if (result != ISC_R_SUCCESS)
02795 goto cleanup;
02796 dns_dns64_append(&view->dns64, dns64);
02797 view->dns64cnt++;
02798 result = dns64_reverse(view, mctx, &na, prefixlen,
02799 server, contact);
02800 if (result != ISC_R_SUCCESS)
02801 goto cleanup;
02802 if (clients != NULL)
02803 dns_acl_detach(&clients);
02804 if (mapped != NULL)
02805 dns_acl_detach(&mapped);
02806 if (excluded != NULL)
02807 dns_acl_detach(&excluded);
02808 }
02809 }
02810
02811 obj = NULL;
02812 result = ns_config_get(maps, "dnssec-accept-expired", &obj);
02813 INSIST(result == ISC_R_SUCCESS);
02814 view->acceptexpired = cfg_obj_asboolean(obj);
02815
02816 obj = NULL;
02817 result = ns_config_get(maps, "dnssec-validation", &obj);
02818 INSIST(result == ISC_R_SUCCESS);
02819 if (cfg_obj_isboolean(obj)) {
02820 view->enablevalidation = cfg_obj_asboolean(obj);
02821 } else {
02822
02823 view->enablevalidation = ISC_TRUE;
02824 auto_root = ISC_TRUE;
02825 }
02826
02827 obj = NULL;
02828 result = ns_config_get(maps, "max-cache-ttl", &obj);
02829 INSIST(result == ISC_R_SUCCESS);
02830 view->maxcachettl = cfg_obj_asuint32(obj);
02831
02832 obj = NULL;
02833 result = ns_config_get(maps, "max-ncache-ttl", &obj);
02834 INSIST(result == ISC_R_SUCCESS);
02835 view->maxncachettl = cfg_obj_asuint32(obj);
02836 if (view->maxncachettl > 7 * 24 * 3600)
02837 view->maxncachettl = 7 * 24 * 3600;
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862 obj = NULL;
02863 result = ns_config_get(maps, "attach-cache", &obj);
02864 if (result == ISC_R_SUCCESS)
02865 cachename = cfg_obj_asstring(obj);
02866 else
02867 cachename = view->name;
02868 cache = NULL;
02869 nsc = cachelist_find(cachelist, cachename);
02870 if (nsc != NULL) {
02871 if (!cache_sharable(nsc->primaryview, view, zero_no_soattl,
02872 cleaning_interval, max_cache_size)) {
02873 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
02874 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
02875 "views %s and %s can't share the cache "
02876 "due to configuration parameter mismatch",
02877 nsc->primaryview->name, view->name);
02878 result = ISC_R_FAILURE;
02879 goto cleanup;
02880 }
02881 dns_cache_attach(nsc->cache, &cache);
02882 shared_cache = ISC_TRUE;
02883 } else {
02884 if (strcmp(cachename, view->name) == 0) {
02885 result = dns_viewlist_find(&ns_g_server->viewlist,
02886 cachename, view->rdclass,
02887 &pview);
02888 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
02889 goto cleanup;
02890 if (pview != NULL) {
02891 if (!cache_reusable(pview, view,
02892 zero_no_soattl)) {
02893 isc_log_write(ns_g_lctx,
02894 NS_LOGCATEGORY_GENERAL,
02895 NS_LOGMODULE_SERVER,
02896 ISC_LOG_DEBUG(1),
02897 "cache cannot be reused "
02898 "for view %s due to "
02899 "configuration parameter "
02900 "mismatch", view->name);
02901 } else {
02902 INSIST(pview->cache != NULL);
02903 isc_log_write(ns_g_lctx,
02904 NS_LOGCATEGORY_GENERAL,
02905 NS_LOGMODULE_SERVER,
02906 ISC_LOG_DEBUG(3),
02907 "reusing existing cache");
02908 reused_cache = ISC_TRUE;
02909 dns_cache_attach(pview->cache, &cache);
02910 }
02911 dns_view_getresstats(pview, &resstats);
02912 dns_view_getresquerystats(pview,
02913 &resquerystats);
02914 dns_view_detach(&pview);
02915 }
02916 }
02917 if (cache == NULL) {
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930 CHECK(isc_mem_create(0, 0, &cmctx));
02931 isc_mem_setname(cmctx, "cache", NULL);
02932 CHECK(isc_mem_create(0, 0, &hmctx));
02933 isc_mem_setname(hmctx, "cache_heap", NULL);
02934 CHECK(dns_cache_create3(cmctx, hmctx, ns_g_taskmgr,
02935 ns_g_timermgr, view->rdclass,
02936 cachename, "rbt", 0, NULL,
02937 &cache));
02938 isc_mem_detach(&cmctx);
02939 isc_mem_detach(&hmctx);
02940 }
02941 nsc = isc_mem_get(mctx, sizeof(*nsc));
02942 if (nsc == NULL) {
02943 result = ISC_R_NOMEMORY;
02944 goto cleanup;
02945 }
02946 nsc->cache = NULL;
02947 dns_cache_attach(cache, &nsc->cache);
02948 nsc->primaryview = view;
02949 nsc->needflush = ISC_FALSE;
02950 nsc->adbsizeadjusted = ISC_FALSE;
02951 ISC_LINK_INIT(nsc, link);
02952 ISC_LIST_APPEND(*cachelist, nsc, link);
02953 }
02954 dns_view_setcache2(view, cache, shared_cache);
02955
02956
02957
02958
02959
02960 obj = NULL;
02961 result = ns_config_get(maps, "cache-file", &obj);
02962 if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
02963 CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
02964 if (!reused_cache && !shared_cache)
02965 CHECK(dns_cache_load(cache));
02966 }
02967
02968 dns_cache_setcleaninginterval(cache, cleaning_interval);
02969 dns_cache_setcachesize(cache, max_cache_size);
02970
02971 dns_cache_detach(&cache);
02972
02973
02974
02975
02976
02977
02978 CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4, &dscp4,
02979 ISC_TF(ISC_LIST_PREV(view, link)
02980 == NULL)));
02981 CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6, &dscp6,
02982 ISC_TF(ISC_LIST_PREV(view, link)
02983 == NULL)));
02984 if (dispatch4 == NULL && dispatch6 == NULL) {
02985 UNEXPECTED_ERROR(__FILE__, __LINE__,
02986 "unable to obtain neither an IPv4 nor"
02987 " an IPv6 dispatch");
02988 result = ISC_R_UNEXPECTED;
02989 goto cleanup;
02990 }
02991
02992 if (resstats == NULL) {
02993 CHECK(isc_stats_create(mctx, &resstats,
02994 dns_resstatscounter_max));
02995 }
02996 dns_view_setresstats(view, resstats);
02997 if (resquerystats == NULL)
02998 CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
02999 dns_view_setresquerystats(view, resquerystats);
03000
03001 ndisp = 4 * ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
03002 CHECK(dns_view_createresolver(view, ns_g_taskmgr, RESOLVER_NTASKS,
03003 ndisp, ns_g_socketmgr, ns_g_timermgr,
03004 resopts, ns_g_dispatchmgr,
03005 dispatch4, dispatch6));
03006
03007 if (dscp4 == -1)
03008 dscp4 = ns_g_dscp;
03009 if (dscp6 == -1)
03010 dscp6 = ns_g_dscp;
03011 if (dscp4 != -1)
03012 dns_resolver_setquerydscp4(view->resolver, dscp4);
03013 if (dscp6 != -1)
03014 dns_resolver_setquerydscp6(view->resolver, dscp6);
03015
03016
03017
03018
03019
03020 max_adb_size = 0;
03021 if (max_cache_size != 0U) {
03022 max_adb_size = max_cache_size / 8;
03023 if (max_adb_size == 0U)
03024 max_adb_size = 1;
03025 if (view != nsc->primaryview &&
03026 max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) {
03027 max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE;
03028 if (!nsc->adbsizeadjusted) {
03029 dns_adb_setadbsize(nsc->primaryview->adb,
03030 MAX_ADB_SIZE_FOR_CACHESHARE);
03031 nsc->adbsizeadjusted = ISC_TRUE;
03032 }
03033 }
03034 }
03035 dns_adb_setadbsize(view->adb, max_adb_size);
03036
03037
03038
03039
03040 obj = NULL;
03041 result = ns_config_get(maps, "lame-ttl", &obj);
03042 INSIST(result == ISC_R_SUCCESS);
03043 lame_ttl = cfg_obj_asuint32(obj);
03044 if (lame_ttl > 1800)
03045 lame_ttl = 1800;
03046 dns_resolver_setlamettl(view->resolver, lame_ttl);
03047
03048
03049
03050
03051 obj = NULL;
03052 result = ns_config_get(maps, "resolver-query-timeout", &obj);
03053 INSIST(result == ISC_R_SUCCESS);
03054 query_timeout = cfg_obj_asuint32(obj);
03055 dns_resolver_settimeout(view->resolver, query_timeout);
03056
03057
03058 dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl);
03059
03060
03061
03062
03063 obj = NULL;
03064 result = ns_config_get(maps, "edns-udp-size", &obj);
03065 INSIST(result == ISC_R_SUCCESS);
03066 udpsize = cfg_obj_asuint32(obj);
03067 if (udpsize < 512)
03068 udpsize = 512;
03069 if (udpsize > 4096)
03070 udpsize = 4096;
03071 dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
03072
03073
03074
03075
03076 obj = NULL;
03077 result = ns_config_get(maps, "max-udp-size", &obj);
03078 INSIST(result == ISC_R_SUCCESS);
03079 udpsize = cfg_obj_asuint32(obj);
03080 if (udpsize < 512)
03081 udpsize = 512;
03082 if (udpsize > 4096)
03083 udpsize = 4096;
03084 view->maxudp = udpsize;
03085
03086 #ifdef ISC_PLATFORM_USESIT
03087
03088
03089
03090 obj = NULL;
03091 result = ns_config_get(maps, "nosit-udp-size", &obj);
03092 INSIST(result == ISC_R_SUCCESS);
03093 udpsize = cfg_obj_asuint32(obj);
03094 if (udpsize < 128)
03095 udpsize = 128;
03096 if (udpsize > view->maxudp)
03097 udpsize = view->maxudp;
03098 view->situdp = udpsize;
03099 #endif
03100
03101
03102
03103
03104 obj = NULL;
03105 result = ns_config_get(maps, "max-rsa-exponent-size", &obj);
03106 INSIST(result == ISC_R_SUCCESS);
03107 maxbits = cfg_obj_asuint32(obj);
03108 if (maxbits != 0 && maxbits < 35)
03109 maxbits = 35;
03110 if (maxbits > 4096)
03111 maxbits = 4096;
03112 view->maxbits = maxbits;
03113
03114
03115
03116
03117 dns_resolver_reset_algorithms(view->resolver);
03118 disabled = NULL;
03119 (void)ns_config_get(maps, "disable-algorithms", &disabled);
03120 if (disabled != NULL) {
03121 for (element = cfg_list_first(disabled);
03122 element != NULL;
03123 element = cfg_list_next(element))
03124 CHECK(disable_algorithms(cfg_listelt_value(element),
03125 view->resolver));
03126 }
03127
03128
03129
03130
03131 dns_resolver_reset_ds_digests(view->resolver);
03132 disabled = NULL;
03133 (void)ns_config_get(maps, "disable-ds-digests", &disabled);
03134 if (disabled != NULL) {
03135 for (element = cfg_list_first(disabled);
03136 element != NULL;
03137 element = cfg_list_next(element))
03138 CHECK(disable_ds_digests(cfg_listelt_value(element),
03139 view->resolver));
03140 }
03141
03142
03143
03144
03145
03146 forwardtype = NULL;
03147 forwarders = NULL;
03148 (void)ns_config_get(maps, "forward", &forwardtype);
03149 (void)ns_config_get(maps, "forwarders", &forwarders);
03150 if (forwarders != NULL)
03151 CHECK(configure_forward(config, view, dns_rootname,
03152 forwarders, forwardtype));
03153
03154
03155
03156
03157 alternates = NULL;
03158 (void)ns_config_get(maps, "dual-stack-servers", &alternates);
03159 if (alternates != NULL)
03160 CHECK(configure_alternates(config, view, alternates));
03161
03162
03163
03164
03165 if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
03166 dns_view_sethints(view, ns_g_server->in_roothints);
03167
03168
03169
03170
03171
03172
03173
03174
03175 if (view->hints == NULL) {
03176 dns_zone_t *rootzone = NULL;
03177 (void)dns_view_findzone(view, dns_rootname, &rootzone);
03178 if (rootzone != NULL) {
03179 dns_zone_detach(&rootzone);
03180 need_hints = ISC_FALSE;
03181 }
03182 if (need_hints)
03183 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
03184 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
03185 "no root hints for view '%s'",
03186 view->name);
03187 }
03188
03189
03190
03191
03192 CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
03193 if (ns_g_server->sessionkey != NULL) {
03194 CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname,
03195 ns_g_server->sessionkey));
03196 }
03197 dns_view_setkeyring(view, ring);
03198 dns_tsigkeyring_detach(&ring);
03199
03200
03201
03202
03203 result = dns_viewlist_find(&ns_g_server->viewlist, view->name,
03204 view->rdclass, &pview);
03205 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
03206 goto cleanup;
03207 if (pview != NULL) {
03208 dns_view_getdynamickeyring(pview, &ring);
03209 if (ring != NULL)
03210 dns_view_setdynamickeyring(view, ring);
03211 dns_tsigkeyring_detach(&ring);
03212 dns_view_detach(&pview);
03213 } else
03214 dns_view_restorekeyring(view);
03215
03216
03217
03218
03219 {
03220 const cfg_obj_t *peers = NULL;
03221 dns_peerlist_t *newpeers = NULL;
03222
03223 (void)ns_config_get(cfgmaps, "server", &peers);
03224 CHECK(dns_peerlist_new(mctx, &newpeers));
03225 for (element = cfg_list_first(peers);
03226 element != NULL;
03227 element = cfg_list_next(element))
03228 {
03229 const cfg_obj_t *cpeer = cfg_listelt_value(element);
03230 dns_peer_t *peer;
03231
03232 CHECK(configure_peer(cpeer, mctx, &peer));
03233 dns_peerlist_addpeer(newpeers, peer);
03234 dns_peer_detach(&peer);
03235 }
03236 dns_peerlist_detach(&view->peers);
03237 view->peers = newpeers;
03238 }
03239
03240
03241
03242
03243 {
03244 const cfg_obj_t *rrsetorder = NULL;
03245
03246 (void)ns_config_get(maps, "rrset-order", &rrsetorder);
03247 CHECK(dns_order_create(mctx, &order));
03248 for (element = cfg_list_first(rrsetorder);
03249 element != NULL;
03250 element = cfg_list_next(element))
03251 {
03252 const cfg_obj_t *ent = cfg_listelt_value(element);
03253
03254 CHECK(configure_order(order, ent));
03255 }
03256 if (view->order != NULL)
03257 dns_order_detach(&view->order);
03258 dns_order_attach(order, &view->order);
03259 dns_order_detach(&order);
03260 }
03261
03262
03263
03264 dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
03265
03266
03267
03268
03269 CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx,
03270 ns_g_mctx, &view->matchclients));
03271 CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL,
03272 actx, ns_g_mctx, &view->matchdestinations));
03273
03274
03275
03276
03277 obj = NULL;
03278 (void)ns_config_get(maps, "match-recursive-only", &obj);
03279 if (obj != NULL && cfg_obj_asboolean(obj))
03280 view->matchrecursiveonly = ISC_TRUE;
03281 else
03282 view->matchrecursiveonly = ISC_FALSE;
03283
03284
03285
03286
03287 obj = NULL;
03288 result = ns_config_get(maps, "recursion", &obj);
03289 INSIST(result == ISC_R_SUCCESS);
03290 view->recursion = cfg_obj_asboolean(obj);
03291
03292 obj = NULL;
03293 result = ns_config_get(maps, "auth-nxdomain", &obj);
03294 INSIST(result == ISC_R_SUCCESS);
03295 view->auth_nxdomain = cfg_obj_asboolean(obj);
03296
03297 obj = NULL;
03298 result = ns_config_get(maps, "minimal-responses", &obj);
03299 INSIST(result == ISC_R_SUCCESS);
03300 view->minimalresponses = cfg_obj_asboolean(obj);
03301
03302 obj = NULL;
03303 result = ns_config_get(maps, "transfer-format", &obj);
03304 INSIST(result == ISC_R_SUCCESS);
03305 str = cfg_obj_asstring(obj);
03306 if (strcasecmp(str, "many-answers") == 0)
03307 view->transfer_format = dns_many_answers;
03308 else if (strcasecmp(str, "one-answer") == 0)
03309 view->transfer_format = dns_one_answer;
03310 else
03311 INSIST(0);
03312
03313
03314
03315
03316
03317 obj = NULL;
03318 result = ns_config_get(maps, "additional-from-auth", &obj);
03319 INSIST(result == ISC_R_SUCCESS);
03320 view->additionalfromauth = cfg_obj_asboolean(obj);
03321 if (view->recursion && ! view->additionalfromauth) {
03322 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
03323 "'additional-from-auth no' is only supported "
03324 "with 'recursion no'");
03325 view->additionalfromauth = ISC_TRUE;
03326 }
03327
03328 obj = NULL;
03329 result = ns_config_get(maps, "additional-from-cache", &obj);
03330 INSIST(result == ISC_R_SUCCESS);
03331 view->additionalfromcache = cfg_obj_asboolean(obj);
03332 if (view->recursion && ! view->additionalfromcache) {
03333 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
03334 "'additional-from-cache no' is only supported "
03335 "with 'recursion no'");
03336 view->additionalfromcache = ISC_TRUE;
03337 }
03338
03339
03340
03341
03342
03343
03344 CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL,
03345 actx, ns_g_mctx, &view->cacheacl));
03346 CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL,
03347 actx, ns_g_mctx, &view->cacheonacl));
03348 if (view->cacheonacl == NULL)
03349 CHECK(configure_view_acl(NULL, ns_g_config,
03350 "allow-query-cache-on", NULL, actx,
03351 ns_g_mctx, &view->cacheonacl));
03352 if (strcmp(view->name, "_bind") != 0) {
03353 CHECK(configure_view_acl(vconfig, config, "allow-recursion",
03354 NULL, actx, ns_g_mctx,
03355 &view->recursionacl));
03356 CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
03357 NULL, actx, ns_g_mctx,
03358 &view->recursiononacl));
03359 }
03360
03361
03362
03363
03364
03365
03366
03367 if (view->cacheacl == NULL && view->recursionacl != NULL)
03368 dns_acl_attach(view->recursionacl, &view->cacheacl);
03369
03370
03371
03372
03373
03374
03375 if (view->cacheacl == NULL && view->recursion)
03376 CHECK(configure_view_acl(vconfig, config, "allow-query", NULL,
03377 actx, ns_g_mctx, &view->cacheacl));
03378 if (view->recursion &&
03379 view->recursionacl == NULL && view->cacheacl != NULL)
03380 dns_acl_attach(view->cacheacl, &view->recursionacl);
03381
03382
03383
03384
03385
03386 if (view->recursionacl == NULL && view->recursion)
03387 CHECK(configure_view_acl(NULL, ns_g_config,
03388 "allow-recursion", NULL,
03389 actx, ns_g_mctx,
03390 &view->recursionacl));
03391 if (view->recursiononacl == NULL && view->recursion)
03392 CHECK(configure_view_acl(NULL, ns_g_config,
03393 "allow-recursion-on", NULL,
03394 actx, ns_g_mctx,
03395 &view->recursiononacl));
03396 if (view->cacheacl == NULL) {
03397 if (view->recursion)
03398 CHECK(configure_view_acl(NULL, ns_g_config,
03399 "allow-query-cache", NULL,
03400 actx, ns_g_mctx,
03401 &view->cacheacl));
03402 else
03403 CHECK(dns_acl_none(mctx, &view->cacheacl));
03404 }
03405
03406
03407
03408
03409
03410
03411 CHECK(configure_view_acl(vconfig, config, "no-case-compress", NULL,
03412 actx, ns_g_mctx, &view->nocasecompress));
03413
03414
03415
03416
03417 CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses",
03418 "acl", actx, ns_g_mctx, &view->denyansweracl));
03419 CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
03420 "except-from", ns_g_mctx,
03421 &view->answeracl_exclude));
03422
03423
03424
03425
03426 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
03427 "name", ns_g_mctx,
03428 &view->denyanswernames));
03429 CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
03430 "except-from", ns_g_mctx,
03431 &view->answernames_exclude));
03432
03433
03434
03435
03436 CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
03437 &view->sortlist));
03438
03439
03440
03441
03442
03443
03444 if (view->notifyacl == NULL)
03445 CHECK(configure_view_acl(NULL, ns_g_config,
03446 "allow-notify", NULL, actx,
03447 ns_g_mctx, &view->notifyacl));
03448 if (view->transferacl == NULL)
03449 CHECK(configure_view_acl(NULL, ns_g_config,
03450 "allow-transfer", NULL, actx,
03451 ns_g_mctx, &view->transferacl));
03452 if (view->updateacl == NULL)
03453 CHECK(configure_view_acl(NULL, ns_g_config,
03454 "allow-update", NULL, actx,
03455 ns_g_mctx, &view->updateacl));
03456 if (view->upfwdacl == NULL)
03457 CHECK(configure_view_acl(NULL, ns_g_config,
03458 "allow-update-forwarding", NULL, actx,
03459 ns_g_mctx, &view->upfwdacl));
03460
03461 obj = NULL;
03462 result = ns_config_get(maps, "provide-ixfr", &obj);
03463 INSIST(result == ISC_R_SUCCESS);
03464 view->provideixfr = cfg_obj_asboolean(obj);
03465
03466 obj = NULL;
03467 result = ns_config_get(maps, "request-nsid", &obj);
03468 INSIST(result == ISC_R_SUCCESS);
03469 view->requestnsid = cfg_obj_asboolean(obj);
03470
03471 #ifdef ISC_PLATFORM_USESIT
03472 obj = NULL;
03473 result = ns_config_get(maps, "request-sit", &obj);
03474 INSIST(result == ISC_R_SUCCESS);
03475 view->requestsit = cfg_obj_asboolean(obj);
03476 #endif
03477
03478 obj = NULL;
03479 result = ns_config_get(maps, "max-clients-per-query", &obj);
03480 INSIST(result == ISC_R_SUCCESS);
03481 max_clients_per_query = cfg_obj_asuint32(obj);
03482
03483 obj = NULL;
03484 result = ns_config_get(maps, "clients-per-query", &obj);
03485 INSIST(result == ISC_R_SUCCESS);
03486 dns_resolver_setclientsperquery(view->resolver,
03487 cfg_obj_asuint32(obj),
03488 max_clients_per_query);
03489
03490 obj = NULL;
03491 result = ns_config_get(maps, "max-recursion-depth", &obj);
03492 INSIST(result == ISC_R_SUCCESS);
03493 dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj));
03494
03495 obj = NULL;
03496 result = ns_config_get(maps, "max-recursion-queries", &obj);
03497 INSIST(result == ISC_R_SUCCESS);
03498 dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj));
03499
03500 #ifdef ALLOW_FILTER_AAAA
03501 obj = NULL;
03502 result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
03503 INSIST(result == ISC_R_SUCCESS);
03504 if (cfg_obj_isboolean(obj)) {
03505 if (cfg_obj_asboolean(obj))
03506 view->v4_aaaa = dns_aaaa_filter;
03507 else
03508 view->v4_aaaa = dns_aaaa_ok;
03509 } else {
03510 const char *v4_aaaastr = cfg_obj_asstring(obj);
03511 if (strcasecmp(v4_aaaastr, "break-dnssec") == 0)
03512 view->v4_aaaa = dns_aaaa_break_dnssec;
03513 else
03514 INSIST(0);
03515 }
03516
03517 obj = NULL;
03518 result = ns_config_get(maps, "filter-aaaa-on-v6", &obj);
03519 INSIST(result == ISC_R_SUCCESS);
03520 if (cfg_obj_isboolean(obj)) {
03521 if (cfg_obj_asboolean(obj))
03522 view->v6_aaaa = dns_aaaa_filter;
03523 else
03524 view->v6_aaaa = dns_aaaa_ok;
03525 } else {
03526 const char *v6_aaaastr = cfg_obj_asstring(obj);
03527 if (strcasecmp(v6_aaaastr, "break-dnssec") == 0)
03528 view->v6_aaaa = dns_aaaa_break_dnssec;
03529 else
03530 INSIST(0);
03531 }
03532
03533 CHECK(configure_view_acl(vconfig, config, "filter-aaaa", NULL,
03534 actx, ns_g_mctx, &view->aaaa_acl));
03535 #endif
03536 obj = NULL;
03537 result = ns_config_get(maps, "prefetch", &obj);
03538 if (result == ISC_R_SUCCESS) {
03539 const cfg_obj_t *trigger, *eligible;
03540
03541 trigger = cfg_tuple_get(obj, "trigger");
03542 view->prefetch_trigger = cfg_obj_asuint32(trigger);
03543 if (view->prefetch_trigger > 10)
03544 view->prefetch_trigger = 10;
03545 eligible = cfg_tuple_get(obj, "eligible");
03546 if (cfg_obj_isvoid(eligible)) {
03547 int m;
03548 for (m = 1; maps[m] != NULL; m++) {
03549 obj = NULL;
03550 result = ns_config_get(&maps[m],
03551 "prefetch", &obj);
03552 INSIST(result == ISC_R_SUCCESS);
03553 eligible = cfg_tuple_get(obj, "eligible");
03554 if (cfg_obj_isuint32(eligible))
03555 break;
03556 }
03557 INSIST(cfg_obj_isuint32(eligible));
03558 }
03559 view->prefetch_eligible = cfg_obj_asuint32(eligible);
03560 if (view->prefetch_eligible < view->prefetch_trigger + 6)
03561 view->prefetch_eligible = view->prefetch_trigger + 6;
03562 }
03563
03564 obj = NULL;
03565 result = ns_config_get(maps, "dnssec-enable", &obj);
03566 INSIST(result == ISC_R_SUCCESS);
03567 view->enablednssec = cfg_obj_asboolean(obj);
03568
03569 obj = NULL;
03570 result = ns_config_get(optionmaps, "dnssec-lookaside", &obj);
03571 if (result == ISC_R_SUCCESS) {
03572
03573 const cfg_obj_t *dlvobj;
03574 const char *dom;
03575 dlvobj = cfg_listelt_value(cfg_list_first(obj));
03576 dom = cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain"));
03577 if (cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) {
03578
03579 if (!strcasecmp(dom, "no"))
03580 result = ISC_R_NOTFOUND;
03581 else if (!strcasecmp(dom, "auto")) {
03582 auto_dlv = ISC_TRUE;
03583 obj = NULL;
03584 result = cfg_map_get(ns_g_defaults,
03585 "dnssec-lookaside", &obj);
03586 }
03587 }
03588 }
03589
03590 if (result == ISC_R_SUCCESS) {
03591 for (element = cfg_list_first(obj);
03592 element != NULL;
03593 element = cfg_list_next(element))
03594 {
03595 dns_name_t *dlv;
03596
03597 obj = cfg_listelt_value(element);
03598 obj = cfg_tuple_get(obj, "trust-anchor");
03599 dlv = dns_fixedname_name(&view->dlv_fixed);
03600 CHECK(dns_name_fromstring(dlv, cfg_obj_asstring(obj),
03601 DNS_NAME_DOWNCASE, NULL));
03602 view->dlv = dns_fixedname_name(&view->dlv_fixed);
03603 }
03604 } else
03605 view->dlv = NULL;
03606
03607
03608
03609
03610
03611 CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys,
03612 auto_dlv, auto_root, mctx));
03613 dns_resolver_resetmustbesecure(view->resolver);
03614 obj = NULL;
03615 result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
03616 if (result == ISC_R_SUCCESS)
03617 CHECK(mustbesecure(obj, view->resolver));
03618
03619 obj = NULL;
03620 result = ns_config_get(maps, "nta-recheck", &obj);
03621 INSIST(result == ISC_R_SUCCESS);
03622 view->nta_recheck = cfg_obj_asuint32(obj);
03623
03624 obj = NULL;
03625 result = ns_config_get(maps, "nta-lifetime", &obj);
03626 INSIST(result == ISC_R_SUCCESS);
03627 view->nta_lifetime = cfg_obj_asuint32(obj);
03628
03629 obj = NULL;
03630 result = ns_config_get(maps, "preferred-glue", &obj);
03631 if (result == ISC_R_SUCCESS) {
03632 str = cfg_obj_asstring(obj);
03633 if (strcasecmp(str, "a") == 0)
03634 view->preferred_glue = dns_rdatatype_a;
03635 else if (strcasecmp(str, "aaaa") == 0)
03636 view->preferred_glue = dns_rdatatype_aaaa;
03637 else
03638 view->preferred_glue = 0;
03639 } else
03640 view->preferred_glue = 0;
03641
03642 obj = NULL;
03643 result = ns_config_get(maps, "root-delegation-only", &obj);
03644 if (result == ISC_R_SUCCESS) {
03645 dns_fixedname_t fixed;
03646 dns_name_t *name;
03647 const cfg_obj_t *exclude;
03648
03649 dns_view_setrootdelonly(view, ISC_TRUE);
03650
03651 dns_fixedname_init(&fixed);
03652 name = dns_fixedname_name(&fixed);
03653 for (element = cfg_list_first(obj);
03654 element != NULL;
03655 element = cfg_list_next(element)) {
03656 exclude = cfg_listelt_value(element);
03657 CHECK(dns_name_fromstring(name,
03658 cfg_obj_asstring(exclude),
03659 0, NULL));
03660 CHECK(dns_view_excludedelegationonly(view, name));
03661 }
03662 } else
03663 dns_view_setrootdelonly(view, ISC_FALSE);
03664
03665
03666
03667
03668
03669 obj = NULL;
03670 (void)ns_config_get(maps, "empty-zones-enable", &obj);
03671 (void)ns_config_get(maps, "disable-empty-zone", &disablelist);
03672 if (obj == NULL && disablelist == NULL &&
03673 view->rdclass == dns_rdataclass_in) {
03674 empty_zones_enable = view->recursion;
03675 } else if (view->rdclass == dns_rdataclass_in) {
03676 if (obj != NULL)
03677 empty_zones_enable = cfg_obj_asboolean(obj);
03678 else
03679 empty_zones_enable = view->recursion;
03680 } else {
03681 empty_zones_enable = ISC_FALSE;
03682 }
03683
03684 if (empty_zones_enable && !lwresd_g_useresolvconf) {
03685 const char *empty;
03686 int empty_zone = 0;
03687 dns_fixedname_t fixed;
03688 dns_name_t *name;
03689 isc_buffer_t buffer;
03690 char server[DNS_NAME_FORMATSIZE + 1];
03691 char contact[DNS_NAME_FORMATSIZE + 1];
03692 const char *empty_dbtype[4] =
03693 { "_builtin", "empty", NULL, NULL };
03694 int empty_dbtypec = 4;
03695 dns_zonestat_level_t statlevel;
03696
03697 dns_fixedname_init(&fixed);
03698 name = dns_fixedname_name(&fixed);
03699
03700 obj = NULL;
03701 result = ns_config_get(maps, "empty-server", &obj);
03702 if (result == ISC_R_SUCCESS) {
03703 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj),
03704 0, NULL));
03705 isc_buffer_init(&buffer, server, sizeof(server) - 1);
03706 CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
03707 server[isc_buffer_usedlength(&buffer)] = 0;
03708 empty_dbtype[2] = server;
03709 } else
03710 empty_dbtype[2] = "@";
03711
03712 obj = NULL;
03713 result = ns_config_get(maps, "empty-contact", &obj);
03714 if (result == ISC_R_SUCCESS) {
03715 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj),
03716 0, NULL));
03717 isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
03718 CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
03719 contact[isc_buffer_usedlength(&buffer)] = 0;
03720 empty_dbtype[3] = contact;
03721 } else
03722 empty_dbtype[3] = ".";
03723
03724 obj = NULL;
03725 result = ns_config_get(maps, "zone-statistics", &obj);
03726 INSIST(result == ISC_R_SUCCESS);
03727 if (cfg_obj_isboolean(obj)) {
03728 if (cfg_obj_asboolean(obj))
03729 statlevel = dns_zonestat_full;
03730 else
03731 statlevel = dns_zonestat_none;
03732 } else {
03733 const char *levelstr = cfg_obj_asstring(obj);
03734 if (strcasecmp(levelstr, "full") == 0)
03735 statlevel = dns_zonestat_full;
03736 else if (strcasecmp(levelstr, "terse") == 0)
03737 statlevel = dns_zonestat_terse;
03738 else if (strcasecmp(levelstr, "none") == 0)
03739 statlevel = dns_zonestat_none;
03740 else
03741 INSIST(0);
03742 }
03743
03744 for (empty = empty_zones[empty_zone];
03745 empty != NULL;
03746 empty = empty_zones[++empty_zone])
03747 {
03748 dns_forwarders_t *dnsforwarders = NULL;
03749
03750
03751
03752
03753 CHECK(dns_name_fromstring(name, empty, 0, NULL));
03754 if (disablelist != NULL &&
03755 on_disable_list(disablelist, name))
03756 continue;
03757
03758
03759
03760
03761 (void)dns_view_findzone(view, name, &zone);
03762 if (zone != NULL) {
03763 dns_zone_detach(&zone);
03764 continue;
03765 }
03766
03767
03768
03769
03770
03771 result = dns_fwdtable_find(view->fwdtable, name,
03772 &dnsforwarders);
03773 if (result == ISC_R_SUCCESS &&
03774 dnsforwarders->fwdpolicy == dns_fwdpolicy_only)
03775 continue;
03776
03777
03778
03779
03780 result = dns_viewlist_find(&ns_g_server->viewlist,
03781 view->name, view->rdclass,
03782 &pview);
03783 if (result != ISC_R_NOTFOUND &&
03784 result != ISC_R_SUCCESS)
03785 goto cleanup;
03786
03787 if (pview != NULL) {
03788 (void)dns_view_findzone(pview, name, &zone);
03789 dns_view_detach(&pview);
03790 }
03791
03792 CHECK(create_empty_zone(zone, name, view, zonelist,
03793 empty_dbtype, empty_dbtypec,
03794 statlevel));
03795 if (zone != NULL)
03796 dns_zone_detach(&zone);
03797 }
03798 }
03799
03800 obj = NULL;
03801 result = ns_config_get(maps, "rate-limit", &obj);
03802 if (result == ISC_R_SUCCESS) {
03803 result = configure_rrl(view, config, obj);
03804 if (result != ISC_R_SUCCESS)
03805 goto cleanup;
03806 }
03807
03808
03809
03810
03811 obj = NULL;
03812 result = ns_config_get(maps, "servfail-ttl", &obj);
03813 INSIST(result == ISC_R_SUCCESS);
03814 fail_ttl = cfg_obj_asuint32(obj);
03815 if (fail_ttl > 300)
03816 fail_ttl = 300;
03817 dns_view_setfailttl(view, fail_ttl);
03818
03819
03820
03821
03822 obj = NULL;
03823 result = ns_config_get(maps, "nxdomain-redirect", &obj);
03824 if (result == ISC_R_SUCCESS) {
03825 dns_name_t *name = dns_fixedname_name(&view->redirectfixed);
03826 CHECK(dns_name_fromstring(name, cfg_obj_asstring(obj), 0,
03827 NULL));
03828 view->redirectzone = name;
03829 } else
03830 view->redirectzone = NULL;
03831
03832
03833 result = ISC_R_SUCCESS;
03834
03835 cleanup:
03836 if (clients != NULL)
03837 dns_acl_detach(&clients);
03838 if (mapped != NULL)
03839 dns_acl_detach(&mapped);
03840 if (excluded != NULL)
03841 dns_acl_detach(&excluded);
03842 if (ring != NULL)
03843 dns_tsigkeyring_detach(&ring);
03844 if (zone != NULL)
03845 dns_zone_detach(&zone);
03846 if (dispatch4 != NULL)
03847 dns_dispatch_detach(&dispatch4);
03848 if (dispatch6 != NULL)
03849 dns_dispatch_detach(&dispatch6);
03850 if (resstats != NULL)
03851 isc_stats_detach(&resstats);
03852 if (resquerystats != NULL)
03853 dns_stats_detach(&resquerystats);
03854 if (order != NULL)
03855 dns_order_detach(&order);
03856 if (cmctx != NULL)
03857 isc_mem_detach(&cmctx);
03858 if (hmctx != NULL)
03859 isc_mem_detach(&hmctx);
03860
03861 if (cache != NULL)
03862 dns_cache_detach(&cache);
03863
03864 return (result);
03865 }
03866
03867 static isc_result_t
03868 configure_hints(dns_view_t *view, const char *filename) {
03869 isc_result_t result;
03870 dns_db_t *db;
03871
03872 db = NULL;
03873 result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
03874 if (result == ISC_R_SUCCESS) {
03875 dns_view_sethints(view, db);
03876 dns_db_detach(&db);
03877 }
03878
03879 return (result);
03880 }
03881
03882 static isc_result_t
03883 configure_alternates(const cfg_obj_t *config, dns_view_t *view,
03884 const cfg_obj_t *alternates)
03885 {
03886 const cfg_obj_t *portobj;
03887 const cfg_obj_t *addresses;
03888 const cfg_listelt_t *element;
03889 isc_result_t result = ISC_R_SUCCESS;
03890 in_port_t port;
03891
03892
03893
03894
03895 if (ns_g_lwresdonly && ns_g_port != 0)
03896 port = ns_g_port;
03897 else
03898 CHECKM(ns_config_getport(config, &port), "port");
03899
03900 if (alternates != NULL) {
03901 portobj = cfg_tuple_get(alternates, "port");
03902 if (cfg_obj_isuint32(portobj)) {
03903 isc_uint32_t val = cfg_obj_asuint32(portobj);
03904 if (val > ISC_UINT16_MAX) {
03905 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
03906 "port '%u' out of range", val);
03907 return (ISC_R_RANGE);
03908 }
03909 port = (in_port_t) val;
03910 }
03911 }
03912
03913 addresses = NULL;
03914 if (alternates != NULL)
03915 addresses = cfg_tuple_get(alternates, "addresses");
03916
03917 for (element = cfg_list_first(addresses);
03918 element != NULL;
03919 element = cfg_list_next(element))
03920 {
03921 const cfg_obj_t *alternate = cfg_listelt_value(element);
03922 isc_sockaddr_t sa;
03923
03924 if (!cfg_obj_issockaddr(alternate)) {
03925 dns_fixedname_t fixed;
03926 dns_name_t *name;
03927 const char *str = cfg_obj_asstring(cfg_tuple_get(
03928 alternate, "name"));
03929 isc_buffer_t buffer;
03930 in_port_t myport = port;
03931
03932 isc_buffer_constinit(&buffer, str, strlen(str));
03933 isc_buffer_add(&buffer, strlen(str));
03934 dns_fixedname_init(&fixed);
03935 name = dns_fixedname_name(&fixed);
03936 CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
03937 NULL));
03938
03939 portobj = cfg_tuple_get(alternate, "port");
03940 if (cfg_obj_isuint32(portobj)) {
03941 isc_uint32_t val = cfg_obj_asuint32(portobj);
03942 if (val > ISC_UINT16_MAX) {
03943 cfg_obj_log(portobj, ns_g_lctx,
03944 ISC_LOG_ERROR,
03945 "port '%u' out of range",
03946 val);
03947 return (ISC_R_RANGE);
03948 }
03949 myport = (in_port_t) val;
03950 }
03951 CHECK(dns_resolver_addalternate(view->resolver, NULL,
03952 name, myport));
03953 continue;
03954 }
03955
03956 sa = *cfg_obj_assockaddr(alternate);
03957 if (isc_sockaddr_getport(&sa) == 0)
03958 isc_sockaddr_setport(&sa, port);
03959 CHECK(dns_resolver_addalternate(view->resolver, &sa,
03960 NULL, 0));
03961 }
03962
03963 cleanup:
03964 return (result);
03965 }
03966
03967 static isc_result_t
03968 configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
03969 const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype)
03970 {
03971 const cfg_obj_t *portobj, *dscpobj;
03972 const cfg_obj_t *faddresses;
03973 const cfg_listelt_t *element;
03974 dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
03975 dns_forwarderlist_t fwdlist;
03976 dns_forwarder_t *fwd;
03977 isc_result_t result;
03978 in_port_t port;
03979 isc_dscp_t dscp = -1;
03980
03981 ISC_LIST_INIT(fwdlist);
03982
03983
03984
03985
03986 if (ns_g_lwresdonly && ns_g_port != 0)
03987 port = ns_g_port;
03988 else
03989 CHECKM(ns_config_getport(config, &port), "port");
03990
03991 if (forwarders != NULL) {
03992 portobj = cfg_tuple_get(forwarders, "port");
03993 if (cfg_obj_isuint32(portobj)) {
03994 isc_uint32_t val = cfg_obj_asuint32(portobj);
03995 if (val > ISC_UINT16_MAX) {
03996 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
03997 "port '%u' out of range", val);
03998 return (ISC_R_RANGE);
03999 }
04000 port = (in_port_t) val;
04001 }
04002 }
04003
04004
04005
04006
04007 dscp = ns_g_dscp;
04008 if (forwarders != NULL) {
04009 dscpobj = cfg_tuple_get(forwarders, "dscp");
04010 if (cfg_obj_isuint32(dscpobj)) {
04011 if (cfg_obj_asuint32(dscpobj) > 63) {
04012 cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
04013 "dscp value '%u' is out of range",
04014 cfg_obj_asuint32(dscpobj));
04015 return (ISC_R_RANGE);
04016 }
04017 dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
04018 }
04019 }
04020
04021 faddresses = NULL;
04022 if (forwarders != NULL)
04023 faddresses = cfg_tuple_get(forwarders, "addresses");
04024
04025 for (element = cfg_list_first(faddresses);
04026 element != NULL;
04027 element = cfg_list_next(element))
04028 {
04029 const cfg_obj_t *forwarder = cfg_listelt_value(element);
04030 fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t));
04031 if (fwd == NULL) {
04032 result = ISC_R_NOMEMORY;
04033 goto cleanup;
04034 }
04035 fwd->addr = *cfg_obj_assockaddr(forwarder);
04036 if (isc_sockaddr_getport(&fwd->addr) == 0)
04037 isc_sockaddr_setport(&fwd->addr, port);
04038 fwd->dscp = cfg_obj_getdscp(forwarder);
04039 if (fwd->dscp == -1)
04040 fwd->dscp = dscp;
04041 ISC_LINK_INIT(fwd, link);
04042 ISC_LIST_APPEND(fwdlist, fwd, link);
04043 }
04044
04045 if (ISC_LIST_EMPTY(fwdlist)) {
04046 if (forwardtype != NULL)
04047 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
04048 "no forwarders seen; disabling "
04049 "forwarding");
04050 fwdpolicy = dns_fwdpolicy_none;
04051 } else {
04052 if (forwardtype == NULL)
04053 fwdpolicy = dns_fwdpolicy_first;
04054 else {
04055 const char *forwardstr = cfg_obj_asstring(forwardtype);
04056 if (strcasecmp(forwardstr, "first") == 0)
04057 fwdpolicy = dns_fwdpolicy_first;
04058 else if (strcasecmp(forwardstr, "only") == 0)
04059 fwdpolicy = dns_fwdpolicy_only;
04060 else
04061 INSIST(0);
04062 }
04063 }
04064
04065 result = dns_fwdtable_addfwd(view->fwdtable, origin, &fwdlist,
04066 fwdpolicy);
04067 if (result != ISC_R_SUCCESS) {
04068 char namebuf[DNS_NAME_FORMATSIZE];
04069 dns_name_format(origin, namebuf, sizeof(namebuf));
04070 cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
04071 "could not set up forwarding for domain '%s': %s",
04072 namebuf, isc_result_totext(result));
04073 goto cleanup;
04074 }
04075
04076 result = ISC_R_SUCCESS;
04077
04078 cleanup:
04079
04080 while (!ISC_LIST_EMPTY(fwdlist)) {
04081 fwd = ISC_LIST_HEAD(fwdlist);
04082 ISC_LIST_UNLINK(fwdlist, fwd, link);
04083 isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t));
04084 }
04085
04086 return (result);
04087 }
04088
04089 static isc_result_t
04090 get_viewinfo(const cfg_obj_t *vconfig, const char **namep,
04091 dns_rdataclass_t *classp)
04092 {
04093 isc_result_t result = ISC_R_SUCCESS;
04094 const char *viewname;
04095 dns_rdataclass_t viewclass;
04096
04097 REQUIRE(namep != NULL && *namep == NULL);
04098 REQUIRE(classp != NULL);
04099
04100 if (vconfig != NULL) {
04101 const cfg_obj_t *classobj = NULL;
04102
04103 viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
04104 classobj = cfg_tuple_get(vconfig, "class");
04105 result = ns_config_getclass(classobj, dns_rdataclass_in,
04106 &viewclass);
04107 } else {
04108 viewname = "_default";
04109 viewclass = dns_rdataclass_in;
04110 }
04111
04112 *namep = viewname;
04113 *classp = viewclass;
04114
04115 return (result);
04116 }
04117
04118
04119
04120
04121
04122
04123 static isc_result_t
04124 find_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
04125 dns_view_t **viewp)
04126 {
04127 isc_result_t result;
04128 const char *viewname = NULL;
04129 dns_rdataclass_t viewclass;
04130 dns_view_t *view = NULL;
04131
04132 result = get_viewinfo(vconfig, &viewname, &viewclass);
04133 if (result != ISC_R_SUCCESS)
04134 return (result);
04135
04136 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
04137 if (result != ISC_R_SUCCESS)
04138 return (result);
04139
04140 *viewp = view;
04141 return (ISC_R_SUCCESS);
04142 }
04143
04144
04145
04146
04147
04148
04149
04150
04151 static isc_result_t
04152 create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
04153 dns_view_t **viewp)
04154 {
04155 isc_result_t result;
04156 const char *viewname = NULL;
04157 dns_rdataclass_t viewclass;
04158 dns_view_t *view = NULL;
04159
04160 result = get_viewinfo(vconfig, &viewname, &viewclass);
04161 if (result != ISC_R_SUCCESS)
04162 return (result);
04163
04164 result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
04165 if (result == ISC_R_SUCCESS)
04166 return (ISC_R_EXISTS);
04167 if (result != ISC_R_NOTFOUND)
04168 return (result);
04169 INSIST(view == NULL);
04170
04171 result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
04172 if (result != ISC_R_SUCCESS)
04173 return (result);
04174
04175 result = isc_entropy_getdata(ns_g_entropy, view->secret,
04176 sizeof(view->secret), NULL, 0);
04177 if (result != ISC_R_SUCCESS) {
04178 dns_view_detach(&view);
04179 return (result);
04180 }
04181
04182 #ifdef HAVE_GEOIP
04183 view->aclenv.geoip = ns_g_geoip;
04184 #endif
04185
04186 ISC_LIST_APPEND(*viewlist, view, link);
04187 dns_view_attach(view, viewp);
04188 return (ISC_R_SUCCESS);
04189 }
04190
04191
04192
04193
04194 static isc_result_t
04195 configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
04196 const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
04197 dns_viewlist_t *viewlist, cfg_aclconfctx_t *aclconf,
04198 isc_boolean_t added, isc_boolean_t old_rpz_ok,
04199 isc_boolean_t modify)
04200 {
04201 dns_view_t *pview = NULL;
04202 dns_zone_t *zone = NULL;
04203 dns_zone_t *raw = NULL;
04204 dns_zone_t *dupzone = NULL;
04205 const cfg_obj_t *options = NULL;
04206 const cfg_obj_t *zoptions = NULL;
04207 const cfg_obj_t *typeobj = NULL;
04208 const cfg_obj_t *forwarders = NULL;
04209 const cfg_obj_t *forwardtype = NULL;
04210 const cfg_obj_t *only = NULL;
04211 const cfg_obj_t *signing = NULL;
04212 const cfg_obj_t *viewobj = NULL;
04213 isc_result_t result;
04214 isc_result_t tresult;
04215 isc_buffer_t buffer;
04216 dns_fixedname_t fixorigin;
04217 dns_name_t *origin;
04218 const char *zname;
04219 dns_rdataclass_t zclass;
04220 const char *ztypestr;
04221 dns_rpz_num_t rpz_num;
04222
04223 options = NULL;
04224 (void)cfg_map_get(config, "options", &options);
04225
04226 zoptions = cfg_tuple_get(zconfig, "options");
04227
04228
04229
04230
04231 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
04232 isc_buffer_constinit(&buffer, zname, strlen(zname));
04233 isc_buffer_add(&buffer, strlen(zname));
04234 dns_fixedname_init(&fixorigin);
04235 CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
04236 &buffer, dns_rootname, 0, NULL));
04237 origin = dns_fixedname_name(&fixorigin);
04238
04239 CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
04240 view->rdclass, &zclass));
04241 if (zclass != view->rdclass) {
04242 const char *vname = NULL;
04243 if (vconfig != NULL)
04244 vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
04245 "name"));
04246 else
04247 vname = "<default view>";
04248
04249 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
04250 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
04251 "zone '%s': wrong class for view '%s'",
04252 zname, vname);
04253 result = ISC_R_FAILURE;
04254 goto cleanup;
04255 }
04256
04257 (void)cfg_map_get(zoptions, "in-view", &viewobj);
04258 if (viewobj != NULL) {
04259 const char *inview = cfg_obj_asstring(viewobj);
04260 dns_view_t *otherview = NULL;
04261
04262 if (viewlist == NULL) {
04263 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
04264 "'in-view' option is not permitted in "
04265 "dynamically added zones");
04266 result = ISC_R_FAILURE;
04267 goto cleanup;
04268 }
04269
04270 result = dns_viewlist_find(viewlist, inview, view->rdclass,
04271 &otherview);
04272 if (result != ISC_R_SUCCESS) {
04273 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
04274 "view '%s' is not yet defined.", inview);
04275 result = ISC_R_FAILURE;
04276 goto cleanup;
04277 }
04278
04279 result = dns_view_findzone(otherview, origin, &zone);
04280 dns_view_detach(&otherview);
04281 if (result != ISC_R_SUCCESS) {
04282 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
04283 "zone '%s' not defined in view '%s'",
04284 zname, inview);
04285 result = ISC_R_FAILURE;
04286 goto cleanup;
04287 }
04288
04289 CHECK(dns_view_addzone(view, zone));
04290 dns_zone_detach(&zone);
04291
04292
04293
04294
04295
04296
04297 forwarders = NULL;
04298 result = cfg_map_get(zoptions, "forwarders", &forwarders);
04299 if (result == ISC_R_SUCCESS) {
04300 forwardtype = NULL;
04301 (void)cfg_map_get(zoptions, "forward", &forwardtype);
04302 CHECK(configure_forward(config, view, origin,
04303 forwarders, forwardtype));
04304 }
04305 result = ISC_R_SUCCESS;
04306 goto cleanup;
04307 }
04308
04309 (void)cfg_map_get(zoptions, "type", &typeobj);
04310 if (typeobj == NULL) {
04311 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
04312 "zone '%s' 'type' not specified", zname);
04313 result = ISC_R_FAILURE;
04314 goto cleanup;
04315 }
04316 ztypestr = cfg_obj_asstring(typeobj);
04317
04318
04319
04320
04321
04322 if (strcasecmp(ztypestr, "hint") == 0) {
04323 const cfg_obj_t *fileobj = NULL;
04324 if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
04325 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
04326 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
04327 "zone '%s': 'file' not specified",
04328 zname);
04329 result = ISC_R_FAILURE;
04330 goto cleanup;
04331 }
04332 if (dns_name_equal(origin, dns_rootname)) {
04333 const char *hintsfile = cfg_obj_asstring(fileobj);
04334
04335 CHECK(configure_hints(view, hintsfile));
04336
04337
04338
04339
04340 only = NULL;
04341 tresult = cfg_map_get(zoptions, "delegation-only",
04342 &only);
04343 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
04344 CHECK(dns_view_adddelegationonly(view, origin));
04345 } else {
04346 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
04347 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
04348 "ignoring non-root hint zone '%s'",
04349 zname);
04350 result = ISC_R_SUCCESS;
04351 }
04352
04353 goto cleanup;
04354 }
04355
04356
04357
04358
04359
04360 if (strcasecmp(ztypestr, "forward") == 0) {
04361 forwardtype = NULL;
04362 forwarders = NULL;
04363
04364 (void)cfg_map_get(zoptions, "forward", &forwardtype);
04365 (void)cfg_map_get(zoptions, "forwarders", &forwarders);
04366 CHECK(configure_forward(config, view, origin, forwarders,
04367 forwardtype));
04368
04369
04370
04371
04372 only = NULL;
04373 tresult = cfg_map_get(zoptions, "delegation-only", &only);
04374 if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
04375 CHECK(dns_view_adddelegationonly(view, origin));
04376 goto cleanup;
04377 }
04378
04379
04380
04381
04382 if (strcasecmp(ztypestr, "delegation-only") == 0) {
04383 result = dns_view_adddelegationonly(view, origin);
04384 goto cleanup;
04385 }
04386
04387
04388
04389
04390 if (strcasecmp(ztypestr, "redirect") == 0) {
04391 if (view->redirect != NULL) {
04392 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
04393 "redirect zone already exists");
04394 result = ISC_R_EXISTS;
04395 goto cleanup;
04396 }
04397 result = dns_viewlist_find(viewlist, view->name,
04398 view->rdclass, &pview);
04399 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
04400 goto cleanup;
04401 if (pview != NULL && pview->redirect != NULL) {
04402 dns_zone_attach(pview->redirect, &zone);
04403 dns_zone_setview(zone, view);
04404 } else {
04405 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr,
04406 &zone));
04407 CHECK(dns_zone_setorigin(zone, origin));
04408 dns_zone_setview(zone, view);
04409 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr,
04410 zone));
04411 dns_zone_setstats(zone, ns_g_server->zonestats);
04412 }
04413 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf,
04414 zone, NULL));
04415 dns_zone_attach(zone, &view->redirect);
04416 goto cleanup;
04417 }
04418
04419 if (!modify) {
04420
04421
04422
04423 result = dns_view_findzone(view, origin, &dupzone);
04424 if (result == ISC_R_SUCCESS) {
04425
04426
04427
04428 cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
04429 "zone '%s' already exists", zname);
04430 dns_zone_detach(&dupzone);
04431 result = ISC_R_EXISTS;
04432 goto cleanup;
04433 }
04434 INSIST(dupzone == NULL);
04435 }
04436
04437
04438
04439
04440 for (rpz_num = 0; ; ++rpz_num) {
04441 if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones) {
04442 rpz_num = DNS_RPZ_INVALID_NUM;
04443 break;
04444 }
04445 if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin))
04446 break;
04447 }
04448
04449
04450
04451
04452
04453
04454
04455
04456
04457
04458
04459
04460
04461 result = dns_viewlist_find(&ns_g_server->viewlist, view->name,
04462 view->rdclass, &pview);
04463 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
04464 goto cleanup;
04465 if (pview != NULL)
04466 result = dns_view_findzone(pview, origin, &zone);
04467 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
04468 goto cleanup;
04469
04470 if (zone != NULL && !ns_zone_reusable(zone, zconfig))
04471 dns_zone_detach(&zone);
04472
04473 if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) ||
04474 (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok)))
04475 dns_zone_detach(&zone);
04476
04477 if (zone != NULL) {
04478
04479
04480
04481
04482 dns_zone_setview(zone, view);
04483 if (view->acache != NULL)
04484 dns_zone_setacache(zone, view->acache);
04485 } else {
04486
04487
04488
04489
04490 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone));
04491 CHECK(dns_zone_setorigin(zone, origin));
04492 dns_zone_setview(zone, view);
04493 if (view->acache != NULL)
04494 dns_zone_setacache(zone, view->acache);
04495 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
04496 dns_zone_setstats(zone, ns_g_server->zonestats);
04497 }
04498
04499 if (rpz_num != DNS_RPZ_INVALID_NUM) {
04500 result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num);
04501 if (result != ISC_R_SUCCESS) {
04502 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
04503 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
04504 "zone '%s': incompatible"
04505 " masterfile-format or database"
04506 " for a response policy zone",
04507 zname);
04508 goto cleanup;
04509 }
04510 }
04511
04512
04513
04514
04515
04516 forwarders = NULL;
04517 if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
04518 {
04519 forwardtype = NULL;
04520 (void)cfg_map_get(zoptions, "forward", &forwardtype);
04521 CHECK(configure_forward(config, view, origin, forwarders,
04522 forwardtype));
04523 }
04524
04525
04526
04527
04528 only = NULL;
04529 if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
04530 {
04531 if (cfg_obj_asboolean(only))
04532 CHECK(dns_view_adddelegationonly(view, origin));
04533 }
04534
04535
04536
04537
04538 dns_zone_setadded(zone, added);
04539
04540 signing = NULL;
04541 if ((strcasecmp(ztypestr, "master") == 0 ||
04542 strcasecmp(ztypestr, "slave") == 0) &&
04543 cfg_map_get(zoptions, "inline-signing", &signing) == ISC_R_SUCCESS &&
04544 cfg_obj_asboolean(signing))
04545 {
04546 dns_zone_getraw(zone, &raw);
04547 if (raw == NULL) {
04548 CHECK(dns_zone_create(&raw, mctx));
04549 CHECK(dns_zone_setorigin(raw, origin));
04550 dns_zone_setview(raw, view);
04551 if (view->acache != NULL)
04552 dns_zone_setacache(raw, view->acache);
04553 dns_zone_setstats(raw, ns_g_server->zonestats);
04554 CHECK(dns_zone_link(zone, raw));
04555 }
04556 }
04557
04558
04559
04560
04561 CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone, raw));
04562
04563
04564
04565
04566 if (!modify)
04567 CHECK(dns_view_addzone(view, zone));
04568
04569
04570
04571
04572 if ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0)
04573 dns_zone_rekey(zone, ISC_FALSE);
04574
04575 cleanup:
04576 if (zone != NULL)
04577 dns_zone_detach(&zone);
04578 if (raw != NULL)
04579 dns_zone_detach(&raw);
04580 if (pview != NULL)
04581 dns_view_detach(&pview);
04582
04583 return (result);
04584 }
04585
04586
04587
04588
04589
04590 static isc_result_t
04591 add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
04592 isc_result_t result;
04593 dns_view_t *pview = NULL;
04594 dns_zone_t *zone = NULL;
04595 dns_acl_t *none = NULL;
04596 char filename[PATH_MAX];
04597 isc_boolean_t defaultview;
04598
04599 REQUIRE(view != NULL);
04600
04601
04602 result = dns_viewlist_find(&ns_g_server->viewlist,
04603 view->name, view->rdclass,
04604 &pview);
04605 if (result != ISC_R_NOTFOUND &&
04606 result != ISC_R_SUCCESS)
04607 return (result);
04608
04609 if (pview != NULL && pview->managed_keys != NULL) {
04610 dns_zone_attach(pview->managed_keys, &view->managed_keys);
04611 dns_zone_setview(pview->managed_keys, view);
04612 dns_view_detach(&pview);
04613 dns_zone_synckeyzone(view->managed_keys);
04614 return (ISC_R_SUCCESS);
04615 }
04616
04617
04618 CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone));
04619 CHECK(dns_zone_setorigin(zone, dns_rootname));
04620
04621 defaultview = ISC_TF(strcmp(view->name, "_default") == 0);
04622 CHECK(isc_file_sanitize(directory,
04623 defaultview ? "managed-keys" : view->name,
04624 defaultview ? "bind" : "mkeys",
04625 filename, sizeof(filename)));
04626 CHECK(dns_zone_setfile(zone, filename));
04627
04628 dns_zone_setview(zone, view);
04629 dns_zone_settype(zone, dns_zone_key);
04630 dns_zone_setclass(zone, view->rdclass);
04631
04632 CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
04633
04634 if (view->acache != NULL)
04635 dns_zone_setacache(zone, view->acache);
04636
04637 CHECK(dns_acl_none(mctx, &none));
04638 dns_zone_setqueryacl(zone, none);
04639 dns_zone_setqueryonacl(zone, none);
04640 dns_acl_detach(&none);
04641
04642 dns_zone_setdialup(zone, dns_dialuptype_no);
04643 dns_zone_setnotifytype(zone, dns_notifytype_no);
04644 dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
04645 dns_zone_setjournalsize(zone, 0);
04646
04647 dns_zone_setstats(zone, ns_g_server->zonestats);
04648 CHECK(setquerystats(zone, mctx, dns_zonestat_none));
04649
04650 if (view->managed_keys != NULL)
04651 dns_zone_detach(&view->managed_keys);
04652 dns_zone_attach(zone, &view->managed_keys);
04653
04654 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
04655 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
04656 "set up managed keys zone for view %s, file '%s'",
04657 view->name, filename);
04658
04659 cleanup:
04660 if (zone != NULL)
04661 dns_zone_detach(&zone);
04662 if (none != NULL)
04663 dns_acl_detach(&none);
04664
04665 return (result);
04666 }
04667
04668
04669
04670
04671 static void
04672 configure_server_quota(const cfg_obj_t **maps, const char *name,
04673 isc_quota_t *quota)
04674 {
04675 const cfg_obj_t *obj = NULL;
04676 isc_result_t result;
04677
04678 result = ns_config_get(maps, name, &obj);
04679 INSIST(result == ISC_R_SUCCESS);
04680 isc_quota_max(quota, cfg_obj_asuint32(obj));
04681 }
04682
04683
04684
04685
04686
04687 static isc_result_t
04688 directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
04689 isc_result_t result;
04690 const char *directory;
04691
04692 REQUIRE(strcasecmp("directory", clausename) == 0);
04693
04694 UNUSED(arg);
04695 UNUSED(clausename);
04696
04697
04698
04699
04700 directory = cfg_obj_asstring(obj);
04701
04702 if (! isc_file_ischdiridempotent(directory))
04703 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
04704 "option 'directory' contains relative path '%s'",
04705 directory);
04706
04707 result = isc_dir_chdir(directory);
04708 if (result != ISC_R_SUCCESS) {
04709 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
04710 "change directory to '%s' failed: %s",
04711 directory, isc_result_totext(result));
04712 return (result);
04713 }
04714
04715 return (ISC_R_SUCCESS);
04716 }
04717
04718 static isc_result_t
04719 scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
04720 isc_result_t result;
04721 isc_boolean_t match_mapped = server->aclenv.match_mapped;
04722 #ifdef HAVE_GEOIP
04723 isc_boolean_t use_ecs = server->aclenv.geoip_use_ecs;
04724 #endif
04725
04726 result = ns_interfacemgr_scan(server->interfacemgr, verbose);
04727
04728
04729
04730
04731 dns_aclenv_copy(&server->aclenv,
04732 ns_interfacemgr_getaclenv(server->interfacemgr));
04733
04734 server->aclenv.match_mapped = match_mapped;
04735 #ifdef HAVE_GEOIP
04736 server->aclenv.geoip_use_ecs = use_ecs;
04737 #endif
04738
04739 return (result);
04740 }
04741
04742 static isc_result_t
04743 add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
04744 isc_dscp_t dscp, isc_boolean_t wcardport_ok)
04745 {
04746 ns_listenelt_t *lelt = NULL;
04747 dns_acl_t *src_acl = NULL;
04748 isc_result_t result;
04749 isc_sockaddr_t any_sa6;
04750 isc_netaddr_t netaddr;
04751
04752 REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
04753
04754 isc_sockaddr_any6(&any_sa6);
04755 if (!isc_sockaddr_equal(&any_sa6, addr) &&
04756 (wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
04757 isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
04758
04759 result = dns_acl_create(mctx, 0, &src_acl);
04760 if (result != ISC_R_SUCCESS)
04761 return (result);
04762
04763 result = dns_iptable_addprefix(src_acl->iptable,
04764 &netaddr, 128, ISC_TRUE);
04765 if (result != ISC_R_SUCCESS)
04766 goto clean;
04767
04768 result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
04769 dscp, src_acl, &lelt);
04770 if (result != ISC_R_SUCCESS)
04771 goto clean;
04772 ISC_LIST_APPEND(list->elts, lelt, link);
04773 }
04774
04775 return (ISC_R_SUCCESS);
04776
04777 clean:
04778 INSIST(lelt == NULL);
04779 dns_acl_detach(&src_acl);
04780
04781 return (result);
04782 }
04783
04784
04785
04786
04787
04788
04789
04790 static void
04791 adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
04792 isc_result_t result;
04793 ns_listenlist_t *list = NULL;
04794 dns_view_t *view;
04795 dns_zone_t *zone, *next;
04796 isc_sockaddr_t addr, *addrp;
04797 isc_dscp_t dscp = -1;
04798
04799 result = ns_listenlist_create(mctx, &list);
04800 if (result != ISC_R_SUCCESS)
04801 return;
04802
04803 for (view = ISC_LIST_HEAD(server->viewlist);
04804 view != NULL;
04805 view = ISC_LIST_NEXT(view, link)) {
04806 dns_dispatch_t *dispatch6;
04807
04808 dispatch6 = dns_resolver_dispatchv6(view->resolver);
04809 if (dispatch6 == NULL)
04810 continue;
04811 result = dns_dispatch_getlocaladdress(dispatch6, &addr);
04812 if (result != ISC_R_SUCCESS)
04813 goto fail;
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824 result = add_listenelt(mctx, list, &addr, dscp, ISC_TRUE);
04825 if (result != ISC_R_SUCCESS)
04826 goto fail;
04827 }
04828
04829 zone = NULL;
04830 for (result = dns_zone_first(server->zonemgr, &zone);
04831 result == ISC_R_SUCCESS;
04832 next = NULL, result = dns_zone_next(zone, &next), zone = next) {
04833 dns_view_t *zoneview;
04834
04835
04836
04837
04838
04839
04840
04841
04842
04843 zoneview = dns_zone_getview(zone);
04844 if (zoneview == NULL)
04845 continue;
04846 for (view = ISC_LIST_HEAD(server->viewlist);
04847 view != NULL && view != zoneview;
04848 view = ISC_LIST_NEXT(view, link))
04849 ;
04850 if (view == NULL)
04851 continue;
04852
04853 addrp = dns_zone_getnotifysrc6(zone);
04854 dscp = dns_zone_getnotifysrc6dscp(zone);
04855 result = add_listenelt(mctx, list, addrp, dscp, ISC_FALSE);
04856 if (result != ISC_R_SUCCESS)
04857 goto fail;
04858
04859 addrp = dns_zone_getxfrsource6(zone);
04860 dscp = dns_zone_getxfrsource6dscp(zone);
04861 result = add_listenelt(mctx, list, addrp, dscp, ISC_FALSE);
04862 if (result != ISC_R_SUCCESS)
04863 goto fail;
04864 }
04865
04866 ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
04867
04868 clean:
04869 ns_listenlist_detach(&list);
04870 return;
04871
04872 fail:
04873
04874
04875
04876
04877 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
04878 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
04879 "could not adjust the listen-on list; "
04880 "some interfaces may not work");
04881 goto clean;
04882 }
04883
04884
04885
04886
04887
04888
04889
04890 static void
04891 interface_timer_tick(isc_task_t *task, isc_event_t *event) {
04892 isc_result_t result;
04893 ns_server_t *server = (ns_server_t *) event->ev_arg;
04894 INSIST(task == server->task);
04895 UNUSED(task);
04896
04897 isc_event_free(&event);
04898
04899
04900
04901
04902
04903 result = isc_task_beginexclusive(server->task);
04904 RUNTIME_CHECK(result == ISC_R_SUCCESS);
04905 scan_interfaces(server, ISC_FALSE);
04906 isc_task_endexclusive(server->task);
04907 }
04908
04909 static void
04910 heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
04911 ns_server_t *server = (ns_server_t *) event->ev_arg;
04912 dns_view_t *view;
04913
04914 UNUSED(task);
04915 isc_event_free(&event);
04916 view = ISC_LIST_HEAD(server->viewlist);
04917 while (view != NULL) {
04918 dns_view_dialup(view);
04919 view = ISC_LIST_NEXT(view, link);
04920 }
04921 }
04922
04923 static void
04924 pps_timer_tick(isc_task_t *task, isc_event_t *event) {
04925 static unsigned int oldrequests = 0;
04926 unsigned int requests = ns_client_requests;
04927
04928 UNUSED(task);
04929 isc_event_free(&event);
04930
04931
04932
04933
04934 dns_pps = (requests - oldrequests) / 1200;
04935 oldrequests = requests;
04936 }
04937
04938
04939
04940
04941
04942
04943 static isc_result_t
04944 setstring(ns_server_t *server, char **field, const char *value) {
04945 char *copy;
04946
04947 if (value != NULL) {
04948 copy = isc_mem_strdup(server->mctx, value);
04949 if (copy == NULL)
04950 return (ISC_R_NOMEMORY);
04951 } else {
04952 copy = NULL;
04953 }
04954
04955 if (*field != NULL)
04956 isc_mem_free(server->mctx, *field);
04957
04958 *field = copy;
04959 return (ISC_R_SUCCESS);
04960 }
04961
04962
04963
04964
04965
04966
04967 static isc_result_t
04968 setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) {
04969 if (cfg_obj_isvoid(obj))
04970 return (setstring(server, field, NULL));
04971 else
04972 return (setstring(server, field, cfg_obj_asstring(obj)));
04973 }
04974
04975 static void
04976 set_limit(const cfg_obj_t **maps, const char *configname,
04977 const char *description, isc_resource_t resourceid,
04978 isc_resourcevalue_t defaultvalue)
04979 {
04980 const cfg_obj_t *obj = NULL;
04981 const char *resource;
04982 isc_resourcevalue_t value;
04983 isc_result_t result;
04984
04985 if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
04986 return;
04987
04988 if (cfg_obj_isstring(obj)) {
04989 resource = cfg_obj_asstring(obj);
04990 if (strcasecmp(resource, "unlimited") == 0)
04991 value = ISC_RESOURCE_UNLIMITED;
04992 else {
04993 INSIST(strcasecmp(resource, "default") == 0);
04994 value = defaultvalue;
04995 }
04996 } else
04997 value = cfg_obj_asuint64(obj);
04998
04999 result = isc_resource_setlimit(resourceid, value);
05000 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
05001 result == ISC_R_SUCCESS ?
05002 ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
05003 "set maximum %s to %" ISC_PRINT_QUADFORMAT "u: %s",
05004 description, value, isc_result_totext(result));
05005 }
05006
05007 #define SETLIMIT(cfgvar, resource, description) \
05008 set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
05009 ns_g_init ## resource)
05010
05011 static void
05012 set_limits(const cfg_obj_t **maps) {
05013 SETLIMIT("stacksize", stacksize, "stack size");
05014 SETLIMIT("datasize", datasize, "data size");
05015 SETLIMIT("coresize", coresize, "core size");
05016 SETLIMIT("files", openfiles, "open files");
05017 }
05018
05019 static void
05020 portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
05021 isc_boolean_t positive)
05022 {
05023 const cfg_listelt_t *element;
05024
05025 for (element = cfg_list_first(ports);
05026 element != NULL;
05027 element = cfg_list_next(element)) {
05028 const cfg_obj_t *obj = cfg_listelt_value(element);
05029
05030 if (cfg_obj_isuint32(obj)) {
05031 in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
05032
05033 if (positive)
05034 isc_portset_add(portset, port);
05035 else
05036 isc_portset_remove(portset, port);
05037 } else {
05038 const cfg_obj_t *obj_loport, *obj_hiport;
05039 in_port_t loport, hiport;
05040
05041 obj_loport = cfg_tuple_get(obj, "loport");
05042 loport = (in_port_t)cfg_obj_asuint32(obj_loport);
05043 obj_hiport = cfg_tuple_get(obj, "hiport");
05044 hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
05045
05046 if (positive)
05047 isc_portset_addrange(portset, loport, hiport);
05048 else {
05049 isc_portset_removerange(portset, loport,
05050 hiport);
05051 }
05052 }
05053 }
05054 }
05055
05056 static isc_result_t
05057 removed(dns_zone_t *zone, void *uap) {
05058 const char *type;
05059
05060 if (dns_zone_getview(zone) != uap)
05061 return (ISC_R_SUCCESS);
05062
05063 switch (dns_zone_gettype(zone)) {
05064 case dns_zone_master:
05065 type = "master";
05066 break;
05067 case dns_zone_slave:
05068 type = "slave";
05069 break;
05070 case dns_zone_stub:
05071 type = "stub";
05072 break;
05073 case dns_zone_staticstub:
05074 type = "static-stub";
05075 break;
05076 case dns_zone_redirect:
05077 type = "redirect";
05078 break;
05079 default:
05080 type = "other";
05081 break;
05082 }
05083 dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type);
05084 return (ISC_R_SUCCESS);
05085 }
05086
05087 static void
05088 cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) {
05089 if (server->session_keyfile != NULL) {
05090 isc_file_remove(server->session_keyfile);
05091 isc_mem_free(mctx, server->session_keyfile);
05092 server->session_keyfile = NULL;
05093 }
05094
05095 if (server->session_keyname != NULL) {
05096 if (dns_name_dynamic(server->session_keyname))
05097 dns_name_free(server->session_keyname, mctx);
05098 isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t));
05099 server->session_keyname = NULL;
05100 }
05101
05102 if (server->sessionkey != NULL)
05103 dns_tsigkey_detach(&server->sessionkey);
05104
05105 server->session_keyalg = DST_ALG_UNKNOWN;
05106 server->session_keybits = 0;
05107 }
05108
05109 static isc_result_t
05110 generate_session_key(const char *filename, const char *keynamestr,
05111 dns_name_t *keyname, const char *algstr,
05112 dns_name_t *algname, unsigned int algtype,
05113 isc_uint16_t bits, isc_mem_t *mctx,
05114 dns_tsigkey_t **tsigkeyp)
05115 {
05116 isc_result_t result = ISC_R_SUCCESS;
05117 dst_key_t *key = NULL;
05118 isc_buffer_t key_txtbuffer;
05119 isc_buffer_t key_rawbuffer;
05120 char key_txtsecret[256];
05121 char key_rawsecret[64];
05122 isc_region_t key_rawregion;
05123 isc_stdtime_t now;
05124 dns_tsigkey_t *tsigkey = NULL;
05125 FILE *fp = NULL;
05126
05127 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05128 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
05129 "generating session key for dynamic DNS");
05130
05131
05132 result = dst_key_generate(keyname, algtype, bits, 1, 0,
05133 DNS_KEYPROTO_ANY, dns_rdataclass_in,
05134 mctx, &key);
05135 if (result != ISC_R_SUCCESS)
05136 return (result);
05137
05138
05139
05140
05141
05142 isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
05143 CHECK(dst_key_tobuffer(key, &key_rawbuffer));
05144
05145 isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
05146 isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
05147 CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer));
05148
05149
05150 isc_stdtime_get(&now);
05151 CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key,
05152 ISC_FALSE, NULL, now, now, mctx, NULL,
05153 &tsigkey));
05154
05155
05156 fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE);
05157 if (fp == NULL) {
05158 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05159 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
05160 "could not create %s", filename);
05161 result = ISC_R_NOPERM;
05162 goto cleanup;
05163 }
05164
05165 fprintf(fp, "key \"%s\" {\n"
05166 "\talgorithm %s;\n"
05167 "\tsecret \"%.*s\";\n};\n", keynamestr, algstr,
05168 (int) isc_buffer_usedlength(&key_txtbuffer),
05169 (char*) isc_buffer_base(&key_txtbuffer));
05170
05171 CHECK(isc_stdio_flush(fp));
05172 CHECK(isc_stdio_close(fp));
05173
05174 dst_key_free(&key);
05175
05176 *tsigkeyp = tsigkey;
05177
05178 return (ISC_R_SUCCESS);
05179
05180 cleanup:
05181 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05182 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
05183 "failed to generate session key "
05184 "for dynamic DNS: %s", isc_result_totext(result));
05185 if (fp != NULL) {
05186 (void)isc_stdio_close(fp);
05187 (void)isc_file_remove(filename);
05188 }
05189 if (tsigkey != NULL)
05190 dns_tsigkey_detach(&tsigkey);
05191 if (key != NULL)
05192 dst_key_free(&key);
05193
05194 return (result);
05195 }
05196
05197 static isc_result_t
05198 configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
05199 isc_mem_t *mctx)
05200 {
05201 const char *keyfile, *keynamestr, *algstr;
05202 unsigned int algtype;
05203 dns_fixedname_t fname;
05204 dns_name_t *keyname, *algname;
05205 isc_buffer_t buffer;
05206 isc_uint16_t bits;
05207 const cfg_obj_t *obj;
05208 isc_boolean_t need_deleteold = ISC_FALSE;
05209 isc_boolean_t need_createnew = ISC_FALSE;
05210 isc_result_t result;
05211
05212 obj = NULL;
05213 result = ns_config_get(maps, "session-keyfile", &obj);
05214 if (result == ISC_R_SUCCESS) {
05215 if (cfg_obj_isvoid(obj))
05216 keyfile = NULL;
05217 else
05218 keyfile = cfg_obj_asstring(obj);
05219 } else
05220 keyfile = ns_g_defaultsessionkeyfile;
05221
05222 obj = NULL;
05223 result = ns_config_get(maps, "session-keyname", &obj);
05224 INSIST(result == ISC_R_SUCCESS);
05225 keynamestr = cfg_obj_asstring(obj);
05226 dns_fixedname_init(&fname);
05227 isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr));
05228 isc_buffer_add(&buffer, strlen(keynamestr));
05229 keyname = dns_fixedname_name(&fname);
05230 result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL);
05231 if (result != ISC_R_SUCCESS)
05232 return (result);
05233
05234 obj = NULL;
05235 result = ns_config_get(maps, "session-keyalg", &obj);
05236 INSIST(result == ISC_R_SUCCESS);
05237 algstr = cfg_obj_asstring(obj);
05238 algname = NULL;
05239 result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits);
05240 if (result != ISC_R_SUCCESS) {
05241 const char *s = " (keeping current key)";
05242
05243 cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: "
05244 "unsupported or unknown algorithm '%s'%s",
05245 algstr,
05246 server->session_keyfile != NULL ? s : "");
05247 return (result);
05248 }
05249
05250
05251 if (keyfile == NULL) {
05252 if (server->session_keyfile != NULL)
05253 need_deleteold = ISC_TRUE;
05254 } else if (server->session_keyfile == NULL)
05255 need_createnew = ISC_TRUE;
05256 else if (strcmp(keyfile, server->session_keyfile) != 0 ||
05257 !dns_name_equal(server->session_keyname, keyname) ||
05258 server->session_keyalg != algtype ||
05259 server->session_keybits != bits) {
05260 need_deleteold = ISC_TRUE;
05261 need_createnew = ISC_TRUE;
05262 }
05263
05264 if (need_deleteold) {
05265 INSIST(server->session_keyfile != NULL);
05266 INSIST(server->session_keyname != NULL);
05267 INSIST(server->sessionkey != NULL);
05268
05269 cleanup_session_key(server, mctx);
05270 }
05271
05272 if (need_createnew) {
05273 INSIST(server->sessionkey == NULL);
05274 INSIST(server->session_keyfile == NULL);
05275 INSIST(server->session_keyname == NULL);
05276 INSIST(server->session_keyalg == DST_ALG_UNKNOWN);
05277 INSIST(server->session_keybits == 0);
05278
05279 server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t));
05280 if (server->session_keyname == NULL)
05281 goto cleanup;
05282 dns_name_init(server->session_keyname, NULL);
05283 CHECK(dns_name_dup(keyname, mctx, server->session_keyname));
05284
05285 server->session_keyfile = isc_mem_strdup(mctx, keyfile);
05286 if (server->session_keyfile == NULL)
05287 goto cleanup;
05288
05289 server->session_keyalg = algtype;
05290 server->session_keybits = bits;
05291
05292 CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr,
05293 algname, algtype, bits, mctx,
05294 &server->sessionkey));
05295 }
05296
05297 return (result);
05298
05299 cleanup:
05300 cleanup_session_key(server, mctx);
05301 return (result);
05302 }
05303
05304 static isc_result_t
05305 setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
05306 cfg_parser_t *conf_parser, cfg_aclconfctx_t *actx)
05307 {
05308 isc_result_t result = ISC_R_SUCCESS;
05309 isc_boolean_t allow = ISC_FALSE;
05310 ns_cfgctx_t *nzcfg = NULL;
05311 const cfg_obj_t *maps[4];
05312 const cfg_obj_t *options = NULL, *voptions = NULL;
05313 const cfg_obj_t *nz = NULL;
05314 int i = 0;
05315
05316 REQUIRE (config != NULL);
05317
05318 if (vconfig != NULL)
05319 voptions = cfg_tuple_get(vconfig, "options");
05320 if (voptions != NULL)
05321 maps[i++] = voptions;
05322 result = cfg_map_get(config, "options", &options);
05323 if (result == ISC_R_SUCCESS)
05324 maps[i++] = options;
05325 maps[i++] = ns_g_defaults;
05326 maps[i] = NULL;
05327
05328 result = ns_config_get(maps, "allow-new-zones", &nz);
05329 if (result == ISC_R_SUCCESS)
05330 allow = cfg_obj_asboolean(nz);
05331
05332 if (!allow) {
05333 dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
05334 return (ISC_R_SUCCESS);
05335 }
05336
05337 nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg));
05338 if (nzcfg == NULL) {
05339 dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
05340 return (ISC_R_NOMEMORY);
05341 }
05342
05343 memset(nzcfg, 0, sizeof(*nzcfg));
05344
05345 dns_view_setnewzones(view, allow, nzcfg, newzone_cfgctx_destroy);
05346
05347 cfg_obj_attach(config, &nzcfg->config);
05348 if (vconfig != NULL)
05349 cfg_obj_attach(vconfig, &nzcfg->vconfig);
05350
05351
05352
05353
05354
05355
05356 cfg_parser_attach(conf_parser, &nzcfg->conf_parser);
05357 cfg_parser_attach(ns_g_addparser, &nzcfg->add_parser);
05358 isc_mem_attach(view->mctx, &nzcfg->mctx);
05359 cfg_aclconfctx_attach(actx, &nzcfg->actx);
05360
05361
05362
05363
05364
05365 cfg_parser_reset(ns_g_addparser);
05366 result = cfg_parse_file(ns_g_addparser, view->new_zone_file,
05367 &cfg_type_newzones, &nzcfg->nzconfig);
05368
05369 return (ISC_R_SUCCESS);
05370 }
05371
05372 static int
05373 count_zones(const cfg_obj_t *conf) {
05374 const cfg_obj_t *zonelist = NULL;
05375 const cfg_listelt_t *element;
05376 int n = 0;
05377
05378 REQUIRE(conf != NULL);
05379
05380 cfg_map_get(conf, "zone", &zonelist);
05381 for (element = cfg_list_first(zonelist);
05382 element != NULL;
05383 element = cfg_list_next(element))
05384 n++;
05385
05386 return (n);
05387 }
05388
05389 static isc_result_t
05390 check_lockfile(ns_server_t *server, const cfg_obj_t *config,
05391 isc_boolean_t first_time)
05392 {
05393 isc_result_t result;
05394 const char *filename = NULL;
05395 const cfg_obj_t *maps[3];
05396 const cfg_obj_t *options;
05397 const cfg_obj_t *obj;
05398 int i;
05399
05400 i = 0;
05401 options = NULL;
05402 result = cfg_map_get(config, "options", &options);
05403 if (result == ISC_R_SUCCESS)
05404 maps[i++] = options;
05405 maps[i++] = ns_g_defaults;
05406 maps[i] = NULL;
05407
05408 obj = NULL;
05409 (void) ns_config_get(maps, "lock-file", &obj);
05410
05411 if (!first_time) {
05412 if (obj != NULL && !cfg_obj_isstring(obj) &&
05413 server->lockfile != NULL &&
05414 strcmp(cfg_obj_asstring(obj), server->lockfile) != 0)
05415 isc_log_write(ns_g_lctx,
05416 NS_LOGCATEGORY_GENERAL,
05417 NS_LOGMODULE_SERVER,
05418 ISC_LOG_WARNING,
05419 "changing 'lock-file' "
05420 "has no effect until the "
05421 "server is restarted");
05422
05423 return (ISC_R_SUCCESS);
05424 }
05425
05426 if (obj != NULL) {
05427 if (cfg_obj_isvoid(obj)) {
05428 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05429 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
05430 "skipping lock-file check ");
05431 return (ISC_R_SUCCESS);
05432 } else if (ns_g_forcelock) {
05433 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05434 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
05435 "'lock-file' has no effect "
05436 "because the server was run with -X");
05437 server->lockfile = isc_mem_strdup(server->mctx,
05438 ns_g_defaultlockfile);
05439 } else {
05440 filename = cfg_obj_asstring(obj);
05441 server->lockfile = isc_mem_strdup(server->mctx,
05442 filename);
05443 }
05444
05445 if (server->lockfile == NULL)
05446 return (ISC_R_NOMEMORY);
05447 }
05448
05449 if (ns_g_forcelock && ns_g_defaultlockfile != NULL) {
05450 INSIST(server->lockfile == NULL);
05451 server->lockfile = isc_mem_strdup(server->mctx,
05452 ns_g_defaultlockfile);
05453 }
05454
05455 if (server->lockfile == NULL)
05456 return (ISC_R_SUCCESS);
05457
05458 if (ns_os_issingleton(server->lockfile))
05459 return (ISC_R_SUCCESS);
05460
05461 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05462 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
05463 "could not lock %s; another named "
05464 "process may be running", server->lockfile);
05465 return (ISC_R_FAILURE);
05466 }
05467
05468 static isc_result_t
05469 load_configuration(const char *filename, ns_server_t *server,
05470 isc_boolean_t first_time)
05471 {
05472 cfg_obj_t *config = NULL, *bindkeys = NULL;
05473 cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL;
05474 const cfg_listelt_t *element;
05475 const cfg_obj_t *builtin_views;
05476 const cfg_obj_t *maps[3];
05477 const cfg_obj_t *obj;
05478 const cfg_obj_t *options;
05479 const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
05480 const cfg_obj_t *views;
05481 dns_view_t *view = NULL;
05482 dns_view_t *view_next;
05483 dns_viewlist_t tmpviewlist;
05484 dns_viewlist_t viewlist, builtin_viewlist;
05485 in_port_t listen_port, udpport_low, udpport_high;
05486 int i;
05487 int num_zones = 0;
05488 isc_boolean_t exclusive = ISC_FALSE;
05489 isc_interval_t interval;
05490 isc_logconfig_t *logc = NULL;
05491 isc_portset_t *v4portset = NULL;
05492 isc_portset_t *v6portset = NULL;
05493 isc_resourcevalue_t nfiles;
05494 isc_result_t result, tresult;
05495 isc_uint32_t heartbeat_interval;
05496 isc_uint32_t interface_interval;
05497 isc_uint32_t reserved;
05498 isc_uint32_t udpsize;
05499 ns_cache_t *nsc;
05500 ns_cachelist_t cachelist, tmpcachelist;
05501 ns_cfgctx_t *nzctx;
05502 unsigned int maxsocks;
05503
05504 ISC_LIST_INIT(viewlist);
05505 ISC_LIST_INIT(builtin_viewlist);
05506 ISC_LIST_INIT(cachelist);
05507
05508
05509 if (ns_g_aclconfctx != NULL)
05510 cfg_aclconfctx_detach(&ns_g_aclconfctx);
05511 CHECK(cfg_aclconfctx_create(ns_g_mctx, &ns_g_aclconfctx));
05512
05513
05514
05515
05516 if (first_time) {
05517 CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
05518 RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
05519 &ns_g_defaults) == ISC_R_SUCCESS);
05520 }
05521
05522
05523
05524
05525 result = ISC_R_FAILURE;
05526 config = NULL;
05527
05528
05529
05530
05531 if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
05532 isc_log_write(ns_g_lctx,
05533 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
05534 ISC_LOG_INFO, "loading configuration from '%s'",
05535 filename);
05536 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
05537 cfg_parser_setcallback(conf_parser, directory_callback, NULL);
05538 result = cfg_parse_file(conf_parser, filename,
05539 &cfg_type_namedconf, &config);
05540 }
05541
05542
05543
05544
05545
05546 if (ns_g_lwresdonly &&
05547 (lwresd_g_useresolvconf ||
05548 (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
05549 {
05550 isc_log_write(ns_g_lctx,
05551 NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
05552 ISC_LOG_INFO, "loading configuration from '%s'",
05553 lwresd_g_resolvconffile);
05554 if (conf_parser != NULL)
05555 cfg_parser_destroy(&conf_parser);
05556 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
05557 result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser,
05558 &config);
05559 }
05560 CHECK(result);
05561
05562
05563
05564
05565 CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
05566
05567
05568
05569
05570 i = 0;
05571 options = NULL;
05572 result = cfg_map_get(config, "options", &options);
05573 if (result == ISC_R_SUCCESS)
05574 maps[i++] = options;
05575 maps[i++] = ns_g_defaults;
05576 maps[i] = NULL;
05577
05578
05579
05580
05581
05582
05583
05584 obj = NULL;
05585 result = ns_config_get(maps, "bindkeys-file", &obj);
05586 INSIST(result == ISC_R_SUCCESS);
05587 CHECKM(setstring(server, &server->bindkeysfile,
05588 cfg_obj_asstring(obj)), "strdup");
05589
05590 if (access(server->bindkeysfile, R_OK) == 0) {
05591 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05592 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
05593 "reading built-in trusted "
05594 "keys from file '%s'", server->bindkeysfile);
05595
05596 CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx,
05597 &bindkeys_parser));
05598
05599 result = cfg_parse_file(bindkeys_parser, server->bindkeysfile,
05600 &cfg_type_bindkeys, &bindkeys);
05601 CHECK(result);
05602 }
05603
05604
05605 if (!exclusive) {
05606 result = isc_task_beginexclusive(server->task);
05607 RUNTIME_CHECK(result == ISC_R_SUCCESS);
05608 exclusive = ISC_TRUE;
05609 }
05610
05611
05612
05613
05614 set_limits(maps);
05615
05616
05617
05618
05619 CHECK(check_lockfile(server, config, first_time));
05620
05621
05622
05623
05624
05625
05626
05627 result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);
05628 if (result != ISC_R_SUCCESS)
05629 maxsocks = 0;
05630 result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
05631 if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
05632 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05633 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
05634 "max open files (%" ISC_PRINT_QUADFORMAT "u)"
05635 " is smaller than max sockets (%u)",
05636 nfiles, maxsocks);
05637 }
05638
05639
05640
05641
05642 obj = NULL;
05643 result = ns_config_get(maps, "reserved-sockets", &obj);
05644 INSIST(result == ISC_R_SUCCESS);
05645 reserved = cfg_obj_asuint32(obj);
05646 if (maxsocks != 0) {
05647 if (maxsocks < 128U)
05648 reserved = 0;
05649 else if (reserved > maxsocks - 128U)
05650 reserved = maxsocks - 128;
05651 }
05652
05653 if (reserved < 128U)
05654 reserved = 128;
05655 if (reserved + 128U > maxsocks && maxsocks != 0) {
05656 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05657 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
05658 "less than 128 UDP sockets available after "
05659 "applying 'reserved-sockets' and 'maxsockets'");
05660 }
05661 isc__socketmgr_setreserved(ns_g_socketmgr, reserved);
05662
05663 #ifdef HAVE_GEOIP
05664
05665
05666
05667
05668
05669
05670 obj = NULL;
05671 result = ns_config_get(maps, "geoip-directory", &obj);
05672 if (result == ISC_R_SUCCESS && cfg_obj_isstring(obj)) {
05673 char *dir;
05674 DE_CONST(cfg_obj_asstring(obj), dir);
05675 ns_geoip_load(dir);
05676 } else
05677 ns_geoip_load(NULL);
05678 ns_g_aclconfctx->geoip = ns_g_geoip;
05679
05680 obj = NULL;
05681 result = ns_config_get(maps, "geoip-use-ecs", &obj);
05682 INSIST(result == ISC_R_SUCCESS);
05683 ns_g_server->aclenv.geoip_use_ecs = cfg_obj_asboolean(obj);
05684 #endif
05685
05686
05687
05688
05689 configure_server_quota(maps, "transfers-out", &server->xfroutquota);
05690 configure_server_quota(maps, "tcp-clients", &server->tcpquota);
05691 configure_server_quota(maps, "recursive-clients",
05692 &server->recursionquota);
05693 if (server->recursionquota.max > 1000)
05694 isc_quota_soft(&server->recursionquota,
05695 server->recursionquota.max - 100);
05696 else
05697 isc_quota_soft(&server->recursionquota, 0);
05698
05699 CHECK(configure_view_acl(NULL, config, "blackhole", NULL,
05700 ns_g_aclconfctx, ns_g_mctx,
05701 &server->blackholeacl));
05702 if (server->blackholeacl != NULL)
05703 dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
05704 server->blackholeacl);
05705
05706 CHECK(configure_view_acl(NULL, config, "keep-response-order", NULL,
05707 ns_g_aclconfctx, ns_g_mctx,
05708 &server->keepresporder));
05709
05710 obj = NULL;
05711 result = ns_config_get(maps, "match-mapped-addresses", &obj);
05712 INSIST(result == ISC_R_SUCCESS);
05713 server->aclenv.match_mapped = cfg_obj_asboolean(obj);
05714
05715 CHECKM(ns_statschannels_configure(ns_g_server, config, ns_g_aclconfctx),
05716 "configuring statistics server(s)");
05717
05718
05719
05720
05721 CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
05722 "creating UDP port set");
05723 CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
05724 "creating UDP port set");
05725
05726 usev4ports = NULL;
05727 usev6ports = NULL;
05728 avoidv4ports = NULL;
05729 avoidv6ports = NULL;
05730
05731 (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
05732 if (usev4ports != NULL)
05733 portset_fromconf(v4portset, usev4ports, ISC_TRUE);
05734 else {
05735 CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
05736 &udpport_high),
05737 "get the default UDP/IPv4 port range");
05738 if (udpport_low == udpport_high)
05739 isc_portset_add(v4portset, udpport_low);
05740 else {
05741 isc_portset_addrange(v4portset, udpport_low,
05742 udpport_high);
05743 }
05744 if (!ns_g_disable4)
05745 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05746 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
05747 "using default UDP/IPv4 port range: "
05748 "[%d, %d]", udpport_low, udpport_high);
05749 }
05750 (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
05751 if (avoidv4ports != NULL)
05752 portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
05753
05754 (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
05755 if (usev6ports != NULL)
05756 portset_fromconf(v6portset, usev6ports, ISC_TRUE);
05757 else {
05758 CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
05759 &udpport_high),
05760 "get the default UDP/IPv6 port range");
05761 if (udpport_low == udpport_high)
05762 isc_portset_add(v6portset, udpport_low);
05763 else {
05764 isc_portset_addrange(v6portset, udpport_low,
05765 udpport_high);
05766 }
05767 if (!ns_g_disable6)
05768 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05769 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
05770 "using default UDP/IPv6 port range: "
05771 "[%d, %d]", udpport_low, udpport_high);
05772 }
05773 (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
05774 if (avoidv6ports != NULL)
05775 portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
05776
05777 dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
05778
05779
05780
05781
05782 obj = NULL;
05783 result = ns_config_get(maps, "edns-udp-size", &obj);
05784 INSIST(result == ISC_R_SUCCESS);
05785 udpsize = cfg_obj_asuint32(obj);
05786 if (udpsize < 512)
05787 udpsize = 512;
05788 if (udpsize > 4096)
05789 udpsize = 4096;
05790 ns_g_udpsize = (isc_uint16_t)udpsize;
05791
05792
05793
05794
05795 obj = NULL;
05796 result = ns_config_get(maps, "transfers-in", &obj);
05797 INSIST(result == ISC_R_SUCCESS);
05798 dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
05799
05800 obj = NULL;
05801 result = ns_config_get(maps, "transfers-per-ns", &obj);
05802 INSIST(result == ISC_R_SUCCESS);
05803 dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
05804
05805 obj = NULL;
05806 result = ns_config_get(maps, "notify-rate", &obj);
05807 INSIST(result == ISC_R_SUCCESS);
05808 dns_zonemgr_setnotifyrate(server->zonemgr, cfg_obj_asuint32(obj));
05809
05810 obj = NULL;
05811 result = ns_config_get(maps, "startup-notify-rate", &obj);
05812 INSIST(result == ISC_R_SUCCESS);
05813 dns_zonemgr_setstartupnotifyrate(server->zonemgr, cfg_obj_asuint32(obj));
05814
05815 obj = NULL;
05816 result = ns_config_get(maps, "serial-query-rate", &obj);
05817 INSIST(result == ISC_R_SUCCESS);
05818 dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
05819
05820
05821
05822
05823 if (ns_g_port != 0)
05824 listen_port = ns_g_port;
05825 else
05826 CHECKM(ns_config_getport(config, &listen_port), "port");
05827
05828
05829
05830
05831 CHECKM(ns_config_getdscp(config, &ns_g_dscp), "dscp");
05832
05833
05834
05835
05836 obj = NULL;
05837 result = ns_config_get(maps, "tcp-listen-queue", &obj);
05838 INSIST(result == ISC_R_SUCCESS);
05839 ns_g_listen = cfg_obj_asuint32(obj);
05840 if ((ns_g_listen > 0) && (ns_g_listen < 10))
05841 ns_g_listen = 10;
05842
05843
05844
05845
05846
05847 {
05848 const cfg_obj_t *clistenon = NULL;
05849 ns_listenlist_t *listenon = NULL;
05850
05851 clistenon = NULL;
05852
05853
05854
05855
05856
05857 if (options != NULL)
05858 (void)cfg_map_get(options, "listen-on", &clistenon);
05859 if (clistenon != NULL) {
05860
05861 (void)ns_listenlist_fromconfig(clistenon, config,
05862 ns_g_aclconfctx,
05863 ns_g_mctx, AF_INET,
05864 &listenon);
05865 } else if (!ns_g_lwresdonly) {
05866
05867
05868
05869 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
05870 -1, ISC_TRUE, &listenon));
05871 }
05872 if (listenon != NULL) {
05873 ns_interfacemgr_setlistenon4(server->interfacemgr,
05874 listenon);
05875 ns_listenlist_detach(&listenon);
05876 }
05877 }
05878
05879
05880
05881 {
05882 const cfg_obj_t *clistenon = NULL;
05883 ns_listenlist_t *listenon = NULL;
05884
05885 if (options != NULL)
05886 (void)cfg_map_get(options, "listen-on-v6", &clistenon);
05887 if (clistenon != NULL) {
05888
05889 (void)ns_listenlist_fromconfig(clistenon, config,
05890 ns_g_aclconfctx,
05891 ns_g_mctx, AF_INET6,
05892 &listenon);
05893 } else if (!ns_g_lwresdonly) {
05894
05895
05896
05897 CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
05898 -1, ISC_TRUE, &listenon));
05899 }
05900 if (listenon != NULL) {
05901 ns_interfacemgr_setlistenon6(server->interfacemgr,
05902 listenon);
05903 ns_listenlist_detach(&listenon);
05904 }
05905 }
05906
05907
05908
05909
05910
05911
05912
05913 result = scan_interfaces(server, ISC_TRUE);
05914
05915
05916
05917
05918
05919
05920 if (first_time && (result == ISC_R_ADDRINUSE)) {
05921 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
05922 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
05923 "unable to listen on any configured interfaces");
05924 result = ISC_R_FAILURE;
05925 goto cleanup;
05926 }
05927
05928
05929
05930
05931
05932 obj = NULL;
05933 result = ns_config_get(maps, "interface-interval", &obj);
05934 INSIST(result == ISC_R_SUCCESS);
05935 interface_interval = cfg_obj_asuint32(obj) * 60;
05936 if (interface_interval == 0) {
05937 CHECK(isc_timer_reset(server->interface_timer,
05938 isc_timertype_inactive,
05939 NULL, NULL, ISC_TRUE));
05940 } else if (server->interface_interval != interface_interval) {
05941 isc_interval_set(&interval, interface_interval, 0);
05942 CHECK(isc_timer_reset(server->interface_timer,
05943 isc_timertype_ticker,
05944 NULL, &interval, ISC_FALSE));
05945 }
05946 server->interface_interval = interface_interval;
05947
05948
05949
05950
05951 obj = NULL;
05952 result = ns_config_get(maps, "automatic-interface-scan", &obj);
05953 INSIST(result == ISC_R_SUCCESS);
05954 server->interface_auto = cfg_obj_asboolean(obj);
05955
05956
05957
05958
05959 obj = NULL;
05960 result = ns_config_get(maps, "heartbeat-interval", &obj);
05961 INSIST(result == ISC_R_SUCCESS);
05962 heartbeat_interval = cfg_obj_asuint32(obj) * 60;
05963 if (heartbeat_interval == 0) {
05964 CHECK(isc_timer_reset(server->heartbeat_timer,
05965 isc_timertype_inactive,
05966 NULL, NULL, ISC_TRUE));
05967 } else if (server->heartbeat_interval != heartbeat_interval) {
05968 isc_interval_set(&interval, heartbeat_interval, 0);
05969 CHECK(isc_timer_reset(server->heartbeat_timer,
05970 isc_timertype_ticker,
05971 NULL, &interval, ISC_FALSE));
05972 }
05973 server->heartbeat_interval = heartbeat_interval;
05974
05975 isc_interval_set(&interval, 1200, 0);
05976 CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
05977 &interval, ISC_FALSE));
05978
05979
05980
05981
05982 obj = NULL;
05983 if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
05984 if (cfg_obj_isvoid(obj))
05985 ns_os_writepidfile(NULL, first_time);
05986 else
05987 ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
05988 else if (ns_g_lwresdonly)
05989 ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
05990 else
05991 ns_os_writepidfile(ns_g_defaultpidfile, first_time);
05992
05993
05994
05995
05996
05997
05998
05999
06000
06001
06002 (void)configure_session_key(maps, server, ns_g_mctx);
06003
06004 views = NULL;
06005 (void)cfg_map_get(config, "view", &views);
06006
06007
06008
06009
06010
06011
06012
06013
06014
06015
06016
06017
06018
06019 for (element = cfg_list_first(views);
06020 element != NULL;
06021 element = cfg_list_next(element))
06022 {
06023 cfg_obj_t *vconfig = cfg_listelt_value(element);
06024 const cfg_obj_t *voptions = cfg_tuple_get(vconfig, "options");
06025 view = NULL;
06026
06027 CHECK(create_view(vconfig, &viewlist, &view));
06028 INSIST(view != NULL);
06029
06030 num_zones += count_zones(voptions);
06031
06032 CHECK(setup_newzones(view, config, vconfig, conf_parser,
06033 ns_g_aclconfctx));
06034 nzctx = view->new_zone_config;
06035 if (nzctx != NULL && nzctx->nzconfig != NULL)
06036 num_zones += count_zones(nzctx->nzconfig);
06037
06038 dns_view_detach(&view);
06039 }
06040
06041
06042
06043
06044
06045 if (views == NULL) {
06046 CHECK(create_view(NULL, &viewlist, &view));
06047 INSIST(view != NULL);
06048
06049 num_zones = count_zones(config);
06050
06051 CHECK(setup_newzones(view, config, NULL, conf_parser,
06052 ns_g_aclconfctx));
06053
06054 nzctx = view->new_zone_config;
06055 if (nzctx != NULL && nzctx->nzconfig != NULL)
06056 num_zones += count_zones(nzctx->nzconfig);
06057
06058 dns_view_detach(&view);
06059 }
06060
06061
06062
06063
06064 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
06065 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
06066 "sizing zone task pool based on %d zones", num_zones);
06067 CHECK(dns_zonemgr_setsize(ns_g_server->zonemgr, num_zones));
06068
06069
06070
06071
06072
06073
06074 for (element = cfg_list_first(views);
06075 element != NULL;
06076 element = cfg_list_next(element))
06077 {
06078 cfg_obj_t *vconfig = cfg_listelt_value(element);
06079
06080 view = NULL;
06081 CHECK(find_view(vconfig, &viewlist, &view));
06082 CHECK(configure_view(view, &viewlist, config, vconfig,
06083 &cachelist, bindkeys, ns_g_mctx,
06084 ns_g_aclconfctx, ISC_TRUE));
06085 dns_view_freeze(view);
06086 dns_view_detach(&view);
06087 }
06088
06089
06090
06091
06092
06093 if (views == NULL) {
06094 view = NULL;
06095 CHECK(find_view(NULL, &viewlist, &view));
06096 CHECK(configure_view(view, &viewlist, config, NULL,
06097 &cachelist, bindkeys,
06098 ns_g_mctx, ns_g_aclconfctx, ISC_TRUE));
06099 dns_view_freeze(view);
06100 dns_view_detach(&view);
06101 }
06102
06103
06104
06105
06106 builtin_views = NULL;
06107 RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
06108 &builtin_views) == ISC_R_SUCCESS);
06109 for (element = cfg_list_first(builtin_views);
06110 element != NULL;
06111 element = cfg_list_next(element))
06112 {
06113 cfg_obj_t *vconfig = cfg_listelt_value(element);
06114
06115 CHECK(create_view(vconfig, &builtin_viewlist, &view));
06116 CHECK(configure_view(view, &viewlist, config, vconfig,
06117 &cachelist, bindkeys,
06118 ns_g_mctx, ns_g_aclconfctx, ISC_FALSE));
06119 dns_view_freeze(view);
06120 dns_view_detach(&view);
06121 view = NULL;
06122 }
06123
06124
06125 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
06126
06127
06128 tmpviewlist = server->viewlist;
06129 server->viewlist = viewlist;
06130 viewlist = tmpviewlist;
06131
06132
06133 view = ISC_LIST_HEAD(server->viewlist);
06134 while (view != NULL) {
06135 view->viewlist = &server->viewlist;
06136 view = ISC_LIST_NEXT(view, link);
06137 }
06138
06139
06140 tmpcachelist = server->cachelist;
06141 server->cachelist = cachelist;
06142 cachelist = tmpcachelist;
06143
06144
06145 if (options != NULL) {
06146 dns_tkeyctx_t *t = NULL;
06147 CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
06148 &t),
06149 "configuring TKEY");
06150 if (server->tkeyctx != NULL)
06151 dns_tkeyctx_destroy(&server->tkeyctx);
06152 server->tkeyctx = t;
06153 }
06154
06155
06156
06157
06158 CHECKM(ns_controls_configure(ns_g_server->controls, config,
06159 ns_g_aclconfctx),
06160 "binding control channel(s)");
06161
06162
06163
06164
06165 CHECKM(ns_lwresd_configure(ns_g_mctx, config),
06166 "binding lightweight resolver ports");
06167
06168
06169
06170
06171 if (first_time) {
06172 obj = NULL;
06173 result = ns_config_get(maps, "random-device", &obj);
06174 if (result != ISC_R_SUCCESS) {
06175 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
06176 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
06177 "no source of entropy found");
06178 } else {
06179 const char *randomdev = cfg_obj_asstring(obj);
06180 result = isc_entropy_createfilesource(ns_g_entropy,
06181 randomdev);
06182 if (result != ISC_R_SUCCESS)
06183 isc_log_write(ns_g_lctx,
06184 NS_LOGCATEGORY_GENERAL,
06185 NS_LOGMODULE_SERVER,
06186 ISC_LOG_INFO,
06187 "could not open entropy source "
06188 "%s: %s",
06189 randomdev,
06190 isc_result_totext(result));
06191 #ifdef PATH_RANDOMDEV
06192 if (ns_g_fallbackentropy != NULL) {
06193 if (result != ISC_R_SUCCESS) {
06194 isc_log_write(ns_g_lctx,
06195 NS_LOGCATEGORY_GENERAL,
06196 NS_LOGMODULE_SERVER,
06197 ISC_LOG_INFO,
06198 "using pre-chroot entropy source "
06199 "%s",
06200 PATH_RANDOMDEV);
06201 isc_entropy_detach(&ns_g_entropy);
06202 isc_entropy_attach(ns_g_fallbackentropy,
06203 &ns_g_entropy);
06204 }
06205 isc_entropy_detach(&ns_g_fallbackentropy);
06206 }
06207 #endif
06208 }
06209 }
06210
06211
06212
06213
06214 if (first_time)
06215 ns_os_changeuser();
06216
06217
06218
06219
06220 if (access(".", W_OK) != 0) {
06221 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
06222 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
06223 "the working directory is not writable");
06224 }
06225
06226
06227
06228
06229
06230
06231
06232
06233 if (ns_g_logstderr) {
06234 const cfg_obj_t *logobj = NULL;
06235
06236 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
06237 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
06238 "not using config file logging "
06239 "statement for logging due to "
06240 "-g option");
06241
06242 (void)cfg_map_get(config, "logging", &logobj);
06243 if (logobj != NULL) {
06244 result = ns_log_configure(NULL, logobj);
06245 if (result != ISC_R_SUCCESS) {
06246 isc_log_write(ns_g_lctx,
06247 NS_LOGCATEGORY_GENERAL,
06248 NS_LOGMODULE_SERVER,
06249 ISC_LOG_ERROR,
06250 "checking logging configuration "
06251 "failed: %s",
06252 isc_result_totext(result));
06253 goto cleanup;
06254 }
06255 }
06256 } else {
06257 const cfg_obj_t *logobj = NULL;
06258
06259 CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
06260 "creating new logging configuration");
06261
06262 logobj = NULL;
06263 (void)cfg_map_get(config, "logging", &logobj);
06264 if (logobj != NULL) {
06265 CHECKM(ns_log_configure(logc, logobj),
06266 "configuring logging");
06267 } else {
06268 CHECKM(ns_log_setdefaultchannels(logc),
06269 "setting up default logging channels");
06270 CHECKM(ns_log_setunmatchedcategory(logc),
06271 "setting up default 'category unmatched'");
06272 CHECKM(ns_log_setdefaultcategory(logc),
06273 "setting up default 'category default'");
06274 }
06275
06276 CHECKM(isc_logconfig_use(ns_g_lctx, logc),
06277 "installing logging configuration");
06278 logc = NULL;
06279
06280 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
06281 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
06282 "now using logging configuration from "
06283 "config file");
06284 }
06285
06286
06287
06288
06289
06290
06291
06292 if (first_time) {
06293 const cfg_obj_t *logobj = NULL;
06294 const cfg_obj_t *categories = NULL;
06295
06296 obj = NULL;
06297 if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
06298 server->log_queries = cfg_obj_asboolean(obj);
06299 } else {
06300
06301 (void)cfg_map_get(config, "logging", &logobj);
06302 if (logobj != NULL)
06303 (void)cfg_map_get(logobj, "category",
06304 &categories);
06305 if (categories != NULL) {
06306 for (element = cfg_list_first(categories);
06307 element != NULL;
06308 element = cfg_list_next(element))
06309 {
06310 const cfg_obj_t *catobj;
06311 const char *str;
06312
06313 obj = cfg_listelt_value(element);
06314 catobj = cfg_tuple_get(obj, "name");
06315 str = cfg_obj_asstring(catobj);
06316 if (strcasecmp(str, "queries") == 0)
06317 server->log_queries = ISC_TRUE;
06318 }
06319 }
06320 }
06321 }
06322
06323
06324 obj = NULL;
06325 if (options != NULL &&
06326 cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
06327 ns_g_memstatistics = cfg_obj_asboolean(obj);
06328 else
06329 ns_g_memstatistics =
06330 ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);
06331
06332 obj = NULL;
06333 if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)
06334 ns_main_setmemstats(cfg_obj_asstring(obj));
06335 else if (ns_g_memstatistics)
06336 ns_main_setmemstats("named.memstats");
06337 else
06338 ns_main_setmemstats(NULL);
06339
06340 obj = NULL;
06341 result = ns_config_get(maps, "statistics-file", &obj);
06342 INSIST(result == ISC_R_SUCCESS);
06343 CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
06344 "strdup");
06345
06346 obj = NULL;
06347 result = ns_config_get(maps, "dump-file", &obj);
06348 INSIST(result == ISC_R_SUCCESS);
06349 CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
06350 "strdup");
06351
06352 obj = NULL;
06353 result = ns_config_get(maps, "secroots-file", &obj);
06354 INSIST(result == ISC_R_SUCCESS);
06355 CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)),
06356 "strdup");
06357
06358 obj = NULL;
06359 result = ns_config_get(maps, "recursing-file", &obj);
06360 INSIST(result == ISC_R_SUCCESS);
06361 CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
06362 "strdup");
06363
06364 obj = NULL;
06365 result = ns_config_get(maps, "version", &obj);
06366 if (result == ISC_R_SUCCESS) {
06367 CHECKM(setoptstring(server, &server->version, obj), "strdup");
06368 server->version_set = ISC_TRUE;
06369 } else {
06370 server->version_set = ISC_FALSE;
06371 }
06372
06373 obj = NULL;
06374 result = ns_config_get(maps, "hostname", &obj);
06375 if (result == ISC_R_SUCCESS) {
06376 CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
06377 server->hostname_set = ISC_TRUE;
06378 } else {
06379 server->hostname_set = ISC_FALSE;
06380 }
06381
06382 obj = NULL;
06383 result = ns_config_get(maps, "server-id", &obj);
06384 server->server_usehostname = ISC_FALSE;
06385 if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
06386
06387 server->server_usehostname = cfg_obj_asboolean(obj);
06388 result = setstring(server, &server->server_id, NULL);
06389 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06390 } else if (result == ISC_R_SUCCESS) {
06391
06392 CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
06393 } else {
06394 result = setstring(server, &server->server_id, NULL);
06395 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06396 }
06397
06398 obj = NULL;
06399 result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
06400 if (result == ISC_R_SUCCESS) {
06401 server->flushonshutdown = cfg_obj_asboolean(obj);
06402 } else {
06403 server->flushonshutdown = ISC_FALSE;
06404 }
06405
06406 #ifdef ISC_PLATFORM_USESIT
06407 obj = NULL;
06408 result = ns_config_get(maps, "sit-secret", &obj);
06409 if (result == ISC_R_SUCCESS) {
06410 isc_buffer_t b;
06411
06412 memset(server->secret, 0, sizeof(server->secret));
06413 isc_buffer_init(&b, server->secret, sizeof(server->secret));
06414 result = isc_hex_decodestring(cfg_obj_asstring(obj), &b);
06415 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
06416 goto cleanup;
06417 #ifdef AES_SIT
06418 if (isc_buffer_usedlength(&b) != ISC_AES128_KEYLENGTH)
06419 CHECKM(ISC_R_RANGE,
06420 "AES sit-secret must be on 128 bits");
06421 #endif
06422 #ifdef HMAC_SHA1_SIT
06423 if (isc_buffer_usedlength(&b) != ISC_SHA1_DIGESTLENGTH)
06424 CHECKM(ISC_R_RANGE,
06425 "SHA1 sit-secret must be on 160 bits");
06426 #endif
06427 #ifdef HMAC_SHA256_SIT
06428 if (isc_buffer_usedlength(&b) != ISC_SHA256_DIGESTLENGTH)
06429 CHECKM(ISC_R_RANGE,
06430 "SHA256 sit-secret must be on 256 bits");
06431 #endif
06432 } else {
06433 result = isc_entropy_getdata(ns_g_entropy,
06434 server->secret,
06435 sizeof(server->secret),
06436 NULL,
06437 0);
06438 if (result != ISC_R_SUCCESS)
06439 goto cleanup;
06440 }
06441 #endif
06442
06443 result = ISC_R_SUCCESS;
06444
06445 cleanup:
06446 if (logc != NULL)
06447 isc_logconfig_destroy(&logc);
06448
06449 if (v4portset != NULL)
06450 isc_portset_destroy(ns_g_mctx, &v4portset);
06451
06452 if (v6portset != NULL)
06453 isc_portset_destroy(ns_g_mctx, &v6portset);
06454
06455 if (conf_parser != NULL) {
06456 if (config != NULL)
06457 cfg_obj_destroy(conf_parser, &config);
06458 cfg_parser_destroy(&conf_parser);
06459 }
06460
06461 if (bindkeys_parser != NULL) {
06462 if (bindkeys != NULL)
06463 cfg_obj_destroy(bindkeys_parser, &bindkeys);
06464 cfg_parser_destroy(&bindkeys_parser);
06465 }
06466
06467 if (view != NULL)
06468 dns_view_detach(&view);
06469
06470 ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
06471
06472
06473
06474
06475
06476
06477 for (view = ISC_LIST_HEAD(viewlist);
06478 view != NULL;
06479 view = view_next) {
06480 view_next = ISC_LIST_NEXT(view, link);
06481 ISC_LIST_UNLINK(viewlist, view, link);
06482 if (result == ISC_R_SUCCESS &&
06483 strcmp(view->name, "_bind") != 0)
06484 (void)dns_zt_apply(view->zonetable, ISC_FALSE,
06485 removed, view);
06486 dns_view_detach(&view);
06487 }
06488
06489
06490 while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) {
06491 ISC_LIST_UNLINK(cachelist, nsc, link);
06492 dns_cache_detach(&nsc->cache);
06493 isc_mem_put(server->mctx, nsc, sizeof(*nsc));
06494 }
06495
06496
06497
06498
06499
06500 if (isc_net_probeipv6() == ISC_R_SUCCESS)
06501 adjust_interfaces(server, ns_g_mctx);
06502
06503
06504
06505
06506 tresult = isc_time_now(&ns_g_configtime);
06507 if (tresult != ISC_R_SUCCESS)
06508 ns_main_earlyfatal("isc_time_now() failed: %s",
06509 isc_result_totext(result));
06510
06511
06512 if (exclusive)
06513 isc_task_endexclusive(server->task);
06514
06515 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
06516 ISC_LOG_DEBUG(1), "load_configuration: %s",
06517 isc_result_totext(result));
06518
06519 return (result);
06520 }
06521
06522 static isc_result_t
06523 view_loaded(void *arg) {
06524 isc_result_t result;
06525 ns_zoneload_t *zl = (ns_zoneload_t *) arg;
06526 ns_server_t *server = zl->server;
06527 unsigned int refs;
06528
06529
06530
06531
06532
06533
06534
06535
06536
06537
06538 isc_refcount_decrement(&zl->refs, &refs);
06539 if (refs != 0)
06540 return (ISC_R_SUCCESS);
06541
06542 isc_refcount_destroy(&zl->refs);
06543 isc_mem_put(server->mctx, zl, sizeof (*zl));
06544
06545 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
06546 ISC_LOG_NOTICE, "all zones loaded");
06547 CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
06548 "forcing zone maintenance");
06549
06550 ns_os_started();
06551 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
06552 ISC_LOG_NOTICE, "running");
06553
06554 return (ISC_R_SUCCESS);
06555 }
06556
06557 static isc_result_t
06558 load_zones(ns_server_t *server, isc_boolean_t init) {
06559 isc_result_t result;
06560 dns_view_t *view;
06561 ns_zoneload_t *zl;
06562 unsigned int refs = 0;
06563
06564 zl = isc_mem_get(server->mctx, sizeof (*zl));
06565 if (zl == NULL)
06566 return (ISC_R_NOMEMORY);
06567 zl->server = server;
06568
06569 result = isc_task_beginexclusive(server->task);
06570 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06571
06572 isc_refcount_init(&zl->refs, 1);
06573
06574
06575
06576
06577 for (view = ISC_LIST_HEAD(server->viewlist);
06578 view != NULL;
06579 view = ISC_LIST_NEXT(view, link))
06580 {
06581 if (view->managed_keys != NULL) {
06582 result = dns_zone_load(view->managed_keys);
06583 if (result != ISC_R_SUCCESS &&
06584 result != DNS_R_UPTODATE &&
06585 result != DNS_R_CONTINUE)
06586 goto cleanup;
06587 }
06588 if (view->redirect != NULL) {
06589 result = dns_zone_load(view->redirect);
06590 if (result != ISC_R_SUCCESS &&
06591 result != DNS_R_UPTODATE &&
06592 result != DNS_R_CONTINUE)
06593 goto cleanup;
06594 }
06595
06596
06597
06598
06599
06600 isc_refcount_increment(&zl->refs, NULL);
06601 CHECK(dns_view_asyncload(view, view_loaded, zl));
06602 }
06603
06604 cleanup:
06605 isc_refcount_decrement(&zl->refs, &refs);
06606 if (refs == 0) {
06607 isc_refcount_destroy(&zl->refs);
06608 isc_mem_put(server->mctx, zl, sizeof (*zl));
06609 } else if (init) {
06610
06611
06612
06613
06614
06615
06616
06617
06618 isc_taskmgr_setmode(ns_g_taskmgr, isc_taskmgrmode_privileged);
06619 }
06620
06621 isc_task_endexclusive(server->task);
06622 return (result);
06623 }
06624
06625 static isc_result_t
06626 load_new_zones(ns_server_t *server, isc_boolean_t stop) {
06627 isc_result_t result;
06628 dns_view_t *view;
06629
06630 result = isc_task_beginexclusive(server->task);
06631 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06632
06633
06634
06635
06636 for (view = ISC_LIST_HEAD(server->viewlist);
06637 view != NULL;
06638 view = ISC_LIST_NEXT(view, link))
06639 {
06640 CHECK(dns_view_loadnew(view, stop));
06641
06642
06643 if (view->managed_keys != NULL)
06644 CHECK(dns_zone_loadnew(view->managed_keys));
06645 if (view->redirect != NULL)
06646 CHECK(dns_zone_loadnew(view->redirect));
06647 }
06648
06649
06650
06651
06652 dns_zonemgr_resumexfrs(server->zonemgr);
06653 cleanup:
06654 isc_task_endexclusive(server->task);
06655 return (result);
06656 }
06657
06658 static void
06659 run_server(isc_task_t *task, isc_event_t *event) {
06660 isc_result_t result;
06661 ns_server_t *server = (ns_server_t *)event->ev_arg;
06662
06663 INSIST(task == server->task);
06664
06665 isc_event_free(&event);
06666
06667 CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
06668 &ns_g_dispatchmgr),
06669 "creating dispatch manager");
06670
06671 dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
06672
06673 CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
06674 ns_g_socketmgr, ns_g_dispatchmgr,
06675 server->task, &server->interfacemgr),
06676 "creating interface manager");
06677
06678 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
06679 NULL, NULL, server->task,
06680 interface_timer_tick,
06681 server, &server->interface_timer),
06682 "creating interface timer");
06683
06684 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
06685 NULL, NULL, server->task,
06686 heartbeat_timer_tick,
06687 server, &server->heartbeat_timer),
06688 "creating heartbeat timer");
06689
06690 CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
06691 NULL, NULL, server->task, pps_timer_tick,
06692 server, &server->pps_timer),
06693 "creating pps timer");
06694
06695 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
06696 "creating default configuration parser");
06697
06698 CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_addparser),
06699 "creating additional configuration parser");
06700
06701 if (ns_g_lwresdonly)
06702 CHECKFATAL(load_configuration(lwresd_g_conffile, server,
06703 ISC_TRUE),
06704 "loading configuration");
06705 else
06706 CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
06707 "loading configuration");
06708
06709 isc_hash_init();
06710
06711 CHECKFATAL(load_zones(server, ISC_TRUE), "loading zones");
06712
06713 (void) ns_server_loadnta(server);
06714 }
06715
06716 void
06717 ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
06718
06719 REQUIRE(NS_SERVER_VALID(server));
06720
06721 server->flushonshutdown = flush;
06722 }
06723
06724 static void
06725 shutdown_server(isc_task_t *task, isc_event_t *event) {
06726 isc_result_t result;
06727 dns_view_t *view, *view_next;
06728 ns_server_t *server = (ns_server_t *)event->ev_arg;
06729 isc_boolean_t flush = server->flushonshutdown;
06730 ns_cache_t *nsc;
06731
06732 UNUSED(task);
06733 INSIST(task == server->task);
06734
06735 result = isc_task_beginexclusive(server->task);
06736 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06737
06738 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
06739 ISC_LOG_INFO, "shutting down%s",
06740 flush ? ": flushing changes" : "");
06741
06742 ns_statschannels_shutdown(server);
06743 ns_controls_shutdown(server->controls);
06744 end_reserved_dispatches(server, ISC_TRUE);
06745 cleanup_session_key(server, server->mctx);
06746
06747 if (ns_g_aclconfctx != NULL)
06748 cfg_aclconfctx_detach(&ns_g_aclconfctx);
06749
06750 cfg_obj_destroy(ns_g_parser, &ns_g_config);
06751 cfg_parser_destroy(&ns_g_parser);
06752 cfg_parser_destroy(&ns_g_addparser);
06753
06754 (void) ns_server_saventa(server);
06755
06756 for (view = ISC_LIST_HEAD(server->viewlist);
06757 view != NULL;
06758 view = view_next) {
06759 view_next = ISC_LIST_NEXT(view, link);
06760 ISC_LIST_UNLINK(server->viewlist, view, link);
06761 if (flush)
06762 dns_view_flushanddetach(&view);
06763 else
06764 dns_view_detach(&view);
06765 }
06766
06767 while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
06768 ISC_LIST_UNLINK(server->cachelist, nsc, link);
06769 dns_cache_detach(&nsc->cache);
06770 isc_mem_put(server->mctx, nsc, sizeof(*nsc));
06771 }
06772
06773 isc_timer_detach(&server->interface_timer);
06774 isc_timer_detach(&server->heartbeat_timer);
06775 isc_timer_detach(&server->pps_timer);
06776
06777 ns_interfacemgr_shutdown(server->interfacemgr);
06778 ns_interfacemgr_detach(&server->interfacemgr);
06779
06780 dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
06781
06782 dns_zonemgr_shutdown(server->zonemgr);
06783
06784 if (ns_g_sessionkey != NULL) {
06785 dns_tsigkey_detach(&ns_g_sessionkey);
06786 dns_name_free(&ns_g_sessionkeyname, server->mctx);
06787 }
06788
06789 if (server->keepresporder != NULL)
06790 dns_acl_detach(&server->keepresporder);
06791
06792 if (server->blackholeacl != NULL)
06793 dns_acl_detach(&server->blackholeacl);
06794
06795 #ifdef HAVE_GEOIP
06796 dns_geoip_shutdown();
06797 #endif
06798
06799 dns_db_detach(&server->in_roothints);
06800
06801 isc_task_endexclusive(server->task);
06802
06803 isc_task_detach(&server->task);
06804
06805 isc_event_free(&event);
06806 }
06807
06808 void
06809 ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
06810 isc_result_t result;
06811 ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
06812
06813 if (server == NULL)
06814 fatal("allocating server object", ISC_R_NOMEMORY);
06815
06816 server->mctx = mctx;
06817 server->task = NULL;
06818
06819
06820 result = isc_quota_init(&server->xfroutquota, 10);
06821 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06822 result = isc_quota_init(&server->tcpquota, 10);
06823 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06824 result = isc_quota_init(&server->recursionquota, 100);
06825 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06826
06827
06828 result = dns_aclenv_init(mctx, &server->aclenv);
06829 RUNTIME_CHECK(result == ISC_R_SUCCESS);
06830
06831 #ifdef HAVE_GEOIP
06832
06833 ns_geoip_init();
06834 server->aclenv.geoip = ns_g_geoip;
06835 #endif
06836
06837
06838 server->zonemgr = NULL;
06839 server->interfacemgr = NULL;
06840 ISC_LIST_INIT(server->viewlist);
06841 server->in_roothints = NULL;
06842 server->blackholeacl = NULL;
06843 server->keepresporder = NULL;
06844
06845
06846 CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy,
06847 ns_g_engine, ISC_ENTROPY_GOODONLY),
06848 "initializing DST");
06849
06850 CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
06851 &server->in_roothints),
06852 "setting up root hints");
06853
06854 CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
06855 "initializing reload event lock");
06856 server->reload_event =
06857 isc_event_allocate(ns_g_mctx, server,
06858 NS_EVENT_RELOAD,
06859 ns_server_reload,
06860 server,
06861 sizeof(isc_event_t));
06862 CHECKFATAL(server->reload_event == NULL ?
06863 ISC_R_NOMEMORY : ISC_R_SUCCESS,
06864 "allocating reload event");
06865
06866 server->tkeyctx = NULL;
06867 CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
06868 &server->tkeyctx),
06869 "creating TKEY context");
06870
06871
06872
06873
06874
06875
06876 CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
06877 "creating server task");
06878 isc_task_setname(server->task, "server", server);
06879 isc_taskmgr_setexcltask(ns_g_taskmgr, server->task);
06880 CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
06881 "isc_task_onshutdown");
06882 CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
06883 "isc_app_onrun");
06884
06885 server->interface_timer = NULL;
06886 server->heartbeat_timer = NULL;
06887 server->pps_timer = NULL;
06888
06889 server->interface_interval = 0;
06890 server->heartbeat_interval = 0;
06891
06892 CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
06893 ns_g_socketmgr, &server->zonemgr),
06894 "dns_zonemgr_create");
06895 CHECKFATAL(dns_zonemgr_setsize(server->zonemgr, 1000),
06896 "dns_zonemgr_setsize");
06897
06898 server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
06899 CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
06900 "isc_mem_strdup");
06901 server->nsstats = NULL;
06902 server->rcvquerystats = NULL;
06903 server->opcodestats = NULL;
06904 server->zonestats = NULL;
06905 server->resolverstats = NULL;
06906 server->sockstats = NULL;
06907 CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats,
06908 isc_sockstatscounter_max),
06909 "isc_stats_create");
06910 isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats);
06911
06912 server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys");
06913 CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY :
06914 ISC_R_SUCCESS,
06915 "isc_mem_strdup");
06916
06917 server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
06918 CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
06919 "isc_mem_strdup");
06920
06921 server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots");
06922 CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY :
06923 ISC_R_SUCCESS,
06924 "isc_mem_strdup");
06925
06926 server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
06927 CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
06928 "isc_mem_strdup");
06929
06930 server->hostname_set = ISC_FALSE;
06931 server->hostname = NULL;
06932 server->version_set = ISC_FALSE;
06933 server->version = NULL;
06934 server->server_usehostname = ISC_FALSE;
06935 server->server_id = NULL;
06936
06937 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats,
06938 dns_nsstatscounter_max),
06939 "dns_stats_create (server)");
06940
06941 CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,
06942 &server->rcvquerystats),
06943 "dns_stats_create (rcvquery)");
06944
06945 CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),
06946 "dns_stats_create (opcode)");
06947
06948 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats,
06949 dns_zonestatscounter_max),
06950 "dns_stats_create (zone)");
06951
06952 CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats,
06953 dns_resstatscounter_max),
06954 "dns_stats_create (resolver)");
06955
06956 server->flushonshutdown = ISC_FALSE;
06957 server->log_queries = ISC_FALSE;
06958
06959 server->controls = NULL;
06960 CHECKFATAL(ns_controls_create(server, &server->controls),
06961 "ns_controls_create");
06962 server->dispatchgen = 0;
06963 ISC_LIST_INIT(server->dispatches);
06964
06965 ISC_LIST_INIT(server->statschannels);
06966
06967 ISC_LIST_INIT(server->cachelist);
06968
06969 server->sessionkey = NULL;
06970 server->session_keyfile = NULL;
06971 server->session_keyname = NULL;
06972 server->session_keyalg = DST_ALG_UNKNOWN;
06973 server->session_keybits = 0;
06974
06975 server->lockfile = NULL;
06976
06977 server->magic = NS_SERVER_MAGIC;
06978 *serverp = server;
06979 }
06980
06981 void
06982 ns_server_destroy(ns_server_t **serverp) {
06983 ns_server_t *server = *serverp;
06984 REQUIRE(NS_SERVER_VALID(server));
06985
06986 ns_controls_destroy(&server->controls);
06987
06988 isc_stats_detach(&server->nsstats);
06989 dns_stats_detach(&server->rcvquerystats);
06990 dns_stats_detach(&server->opcodestats);
06991 isc_stats_detach(&server->zonestats);
06992 isc_stats_detach(&server->resolverstats);
06993 isc_stats_detach(&server->sockstats);
06994
06995 isc_mem_free(server->mctx, server->statsfile);
06996 isc_mem_free(server->mctx, server->bindkeysfile);
06997 isc_mem_free(server->mctx, server->dumpfile);
06998 isc_mem_free(server->mctx, server->secrootsfile);
06999 isc_mem_free(server->mctx, server->recfile);
07000
07001 if (server->version != NULL)
07002 isc_mem_free(server->mctx, server->version);
07003 if (server->hostname != NULL)
07004 isc_mem_free(server->mctx, server->hostname);
07005 if (server->server_id != NULL)
07006 isc_mem_free(server->mctx, server->server_id);
07007 if (server->lockfile != NULL)
07008 isc_mem_free(server->mctx, server->lockfile);
07009
07010 if (server->zonemgr != NULL)
07011 dns_zonemgr_detach(&server->zonemgr);
07012
07013 if (server->tkeyctx != NULL)
07014 dns_tkeyctx_destroy(&server->tkeyctx);
07015
07016 dst_lib_destroy();
07017
07018 isc_event_free(&server->reload_event);
07019
07020 INSIST(ISC_LIST_EMPTY(server->viewlist));
07021 INSIST(ISC_LIST_EMPTY(server->cachelist));
07022
07023 dns_aclenv_destroy(&server->aclenv);
07024
07025 isc_quota_destroy(&server->recursionquota);
07026 isc_quota_destroy(&server->tcpquota);
07027 isc_quota_destroy(&server->xfroutquota);
07028
07029 server->magic = 0;
07030 isc_mem_put(server->mctx, server, sizeof(*server));
07031 *serverp = NULL;
07032 }
07033
07034 static void
07035 fatal(const char *msg, isc_result_t result) {
07036 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
07037 ISC_LOG_CRITICAL, "%s: %s", msg,
07038 isc_result_totext(result));
07039 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
07040 ISC_LOG_CRITICAL, "exiting (due to fatal error)");
07041 ns_os_shutdown();
07042 exit(1);
07043 }
07044
07045 static void
07046 start_reserved_dispatches(ns_server_t *server) {
07047
07048 REQUIRE(NS_SERVER_VALID(server));
07049
07050 server->dispatchgen++;
07051 }
07052
07053 static void
07054 end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
07055 ns_dispatch_t *dispatch, *nextdispatch;
07056
07057 REQUIRE(NS_SERVER_VALID(server));
07058
07059 for (dispatch = ISC_LIST_HEAD(server->dispatches);
07060 dispatch != NULL;
07061 dispatch = nextdispatch) {
07062 nextdispatch = ISC_LIST_NEXT(dispatch, link);
07063 if (!all && server->dispatchgen == dispatch-> dispatchgen)
07064 continue;
07065 ISC_LIST_UNLINK(server->dispatches, dispatch, link);
07066 dns_dispatch_detach(&dispatch->dispatch);
07067 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
07068 }
07069 }
07070
07071 void
07072 ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) {
07073 ns_dispatch_t *dispatch;
07074 in_port_t port;
07075 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
07076 isc_result_t result;
07077 unsigned int attrs, attrmask;
07078
07079 REQUIRE(NS_SERVER_VALID(server));
07080
07081 port = isc_sockaddr_getport(addr);
07082 if (port == 0 || port >= 1024)
07083 return;
07084
07085 for (dispatch = ISC_LIST_HEAD(server->dispatches);
07086 dispatch != NULL;
07087 dispatch = ISC_LIST_NEXT(dispatch, link)) {
07088 if (isc_sockaddr_equal(&dispatch->addr, addr))
07089 break;
07090 }
07091 if (dispatch != NULL) {
07092 dispatch->dispatchgen = server->dispatchgen;
07093 return;
07094 }
07095
07096 dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
07097 if (dispatch == NULL) {
07098 result = ISC_R_NOMEMORY;
07099 goto cleanup;
07100 }
07101
07102 dispatch->addr = *addr;
07103 dispatch->dispatchgen = server->dispatchgen;
07104 dispatch->dispatch = NULL;
07105
07106 attrs = 0;
07107 attrs |= DNS_DISPATCHATTR_UDP;
07108 switch (isc_sockaddr_pf(addr)) {
07109 case AF_INET:
07110 attrs |= DNS_DISPATCHATTR_IPV4;
07111 break;
07112 case AF_INET6:
07113 attrs |= DNS_DISPATCHATTR_IPV6;
07114 break;
07115 default:
07116 result = ISC_R_NOTIMPLEMENTED;
07117 goto cleanup;
07118 }
07119 attrmask = 0;
07120 attrmask |= DNS_DISPATCHATTR_UDP;
07121 attrmask |= DNS_DISPATCHATTR_TCP;
07122 attrmask |= DNS_DISPATCHATTR_IPV4;
07123 attrmask |= DNS_DISPATCHATTR_IPV6;
07124
07125 result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
07126 ns_g_taskmgr, &dispatch->addr, 4096,
07127 UDPBUFFERS, 32768, 16411, 16433,
07128 attrs, attrmask, &dispatch->dispatch);
07129 if (result != ISC_R_SUCCESS)
07130 goto cleanup;
07131
07132 ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
07133
07134 return;
07135
07136 cleanup:
07137 if (dispatch != NULL)
07138 isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
07139 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
07140 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07141 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
07142 "unable to create dispatch for reserved port %s: %s",
07143 addrbuf, isc_result_totext(result));
07144 }
07145
07146
07147 static isc_result_t
07148 loadconfig(ns_server_t *server) {
07149 isc_result_t result;
07150 start_reserved_dispatches(server);
07151 result = load_configuration(ns_g_lwresdonly ?
07152 lwresd_g_conffile : ns_g_conffile,
07153 server, ISC_FALSE);
07154 if (result == ISC_R_SUCCESS) {
07155 end_reserved_dispatches(server, ISC_FALSE);
07156 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07157 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07158 "reloading configuration succeeded");
07159 } else {
07160 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07161 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
07162 "reloading configuration failed: %s",
07163 isc_result_totext(result));
07164 }
07165
07166 return (result);
07167 }
07168
07169 static isc_result_t
07170 reload(ns_server_t *server) {
07171 isc_result_t result;
07172 CHECK(loadconfig(server));
07173
07174 result = load_zones(server, ISC_FALSE);
07175 if (result == ISC_R_SUCCESS)
07176 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07177 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07178 "reloading zones succeeded");
07179 else
07180 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07181 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
07182 "reloading zones failed: %s",
07183 isc_result_totext(result));
07184
07185 cleanup:
07186 return (result);
07187 }
07188
07189 static void
07190 reconfig(ns_server_t *server) {
07191 isc_result_t result;
07192 CHECK(loadconfig(server));
07193
07194 result = load_new_zones(server, ISC_FALSE);
07195 if (result == ISC_R_SUCCESS)
07196 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07197 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07198 "any newly configured zones are now loaded");
07199 else
07200 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07201 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
07202 "loading new zones failed: %s",
07203 isc_result_totext(result));
07204
07205 cleanup: ;
07206 }
07207
07208
07209
07210
07211 static void
07212 ns_server_reload(isc_task_t *task, isc_event_t *event) {
07213 ns_server_t *server = (ns_server_t *)event->ev_arg;
07214
07215 INSIST(task = server->task);
07216 UNUSED(task);
07217
07218 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07219 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07220 "received SIGHUP signal to reload zones");
07221 (void)reload(server);
07222
07223 LOCK(&server->reload_event_lock);
07224 INSIST(server->reload_event == NULL);
07225 server->reload_event = event;
07226 UNLOCK(&server->reload_event_lock);
07227 }
07228
07229 void
07230 ns_server_reloadwanted(ns_server_t *server) {
07231 LOCK(&server->reload_event_lock);
07232 if (server->reload_event != NULL)
07233 isc_task_send(server->task, &server->reload_event);
07234 UNLOCK(&server->reload_event_lock);
07235 }
07236
07237 void
07238 ns_server_scan_interfaces(ns_server_t *server) {
07239 isc_result_t result;
07240
07241 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07242 NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
07243 "automatic interface rescan");
07244
07245 result = isc_task_beginexclusive(server->task);
07246 RUNTIME_CHECK(result == ISC_R_SUCCESS);
07247 scan_interfaces(server, ISC_TRUE);
07248 isc_task_endexclusive(server->task);
07249 }
07250
07251 static char *
07252 next_token(char **stringp, const char *delim) {
07253 char *res;
07254
07255 do {
07256 res = strsep(stringp, delim);
07257 if (res == NULL)
07258 break;
07259 } while (*res == '\0');
07260 return (res);
07261 }
07262
07263
07264
07265
07266
07267
07268
07269
07270
07271
07272
07273 static isc_result_t
07274 zone_from_args(ns_server_t *server, char *args, const char *zonetxt,
07275 dns_zone_t **zonep, const char **zonename,
07276 isc_buffer_t **text, isc_boolean_t skip)
07277 {
07278 char *input, *ptr;
07279 char *classtxt;
07280 const char *viewtxt = NULL;
07281 dns_fixedname_t fname;
07282 dns_name_t *name;
07283 isc_result_t result;
07284 dns_view_t *view = NULL;
07285 dns_rdataclass_t rdclass;
07286 char problem[DNS_NAME_FORMATSIZE + 500] = "";
07287
07288 REQUIRE(zonep != NULL && *zonep == NULL);
07289 REQUIRE(zonename == NULL || *zonename == NULL);
07290
07291 input = args;
07292
07293 if (skip) {
07294
07295 ptr = next_token(&input, " \t");
07296 if (ptr == NULL)
07297 return (ISC_R_UNEXPECTEDEND);
07298 }
07299
07300
07301 if (zonetxt == NULL)
07302 zonetxt = next_token(&input, " \t");
07303 if (zonetxt == NULL)
07304 return (ISC_R_SUCCESS);
07305 if (zonename != NULL)
07306 *zonename = zonetxt;
07307
07308
07309 classtxt = next_token(&input, " \t");
07310 if (classtxt != NULL) {
07311
07312 viewtxt = next_token(&input, " \t");
07313 }
07314
07315 dns_fixedname_init(&fname);
07316 name = dns_fixedname_name(&fname);
07317 CHECK(dns_name_fromstring(name, zonetxt, 0, NULL));
07318
07319 if (classtxt != NULL) {
07320 isc_textregion_t r;
07321 r.base = classtxt;
07322 r.length = strlen(classtxt);
07323 CHECK(dns_rdataclass_fromtext(&rdclass, &r));
07324 } else
07325 rdclass = dns_rdataclass_in;
07326
07327 if (viewtxt == NULL) {
07328 result = dns_viewlist_findzone(&server->viewlist, name,
07329 ISC_TF(classtxt == NULL),
07330 rdclass, zonep);
07331 if (result == ISC_R_NOTFOUND)
07332 snprintf(problem, sizeof(problem),
07333 "no matching zone '%s' in any view",
07334 zonetxt);
07335 else if (result == ISC_R_MULTIPLE)
07336 snprintf(problem, sizeof(problem),
07337 "zone '%s' was found in multiple views",
07338 zonetxt);
07339 } else {
07340 result = dns_viewlist_find(&server->viewlist, viewtxt,
07341 rdclass, &view);
07342 if (result != ISC_R_SUCCESS) {
07343 snprintf(problem, sizeof(problem),
07344 "no matching view '%s'", viewtxt);
07345 goto report;
07346 }
07347
07348 result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
07349 if (result != ISC_R_SUCCESS)
07350 snprintf(problem, sizeof(problem),
07351 "no matching zone '%s' in view '%s'",
07352 zonetxt, viewtxt);
07353 }
07354
07355
07356 if (result != ISC_R_SUCCESS && *zonep != NULL)
07357 dns_zone_detach(zonep);
07358 if (result == DNS_R_PARTIALMATCH)
07359 result = ISC_R_NOTFOUND;
07360 report:
07361 if (result != ISC_R_SUCCESS) {
07362 isc_result_t tresult;
07363
07364 tresult = putstr(text, problem);
07365 if (tresult == ISC_R_SUCCESS)
07366 (void) putnull(text);
07367 }
07368
07369 cleanup:
07370 if (view != NULL)
07371 dns_view_detach(&view);
07372
07373 return (result);
07374 }
07375
07376
07377
07378
07379 isc_result_t
07380 ns_server_retransfercommand(ns_server_t *server, char *args,
07381 isc_buffer_t **text)
07382 {
07383 isc_result_t result;
07384 dns_zone_t *zone = NULL;
07385 dns_zone_t *raw = NULL;
07386 dns_zonetype_t type;
07387
07388 result = zone_from_args(server, args, NULL, &zone, NULL,
07389 text, ISC_TRUE);
07390 if (result != ISC_R_SUCCESS)
07391 return (result);
07392 if (zone == NULL)
07393 return (ISC_R_UNEXPECTEDEND);
07394 dns_zone_getraw(zone, &raw);
07395 if (raw != NULL) {
07396 dns_zone_detach(&zone);
07397 dns_zone_attach(raw, &zone);
07398 dns_zone_detach(&raw);
07399 }
07400 type = dns_zone_gettype(zone);
07401 if (type == dns_zone_slave || type == dns_zone_stub)
07402 dns_zone_forcereload(zone);
07403 else
07404 result = ISC_R_NOTFOUND;
07405 dns_zone_detach(&zone);
07406 return (result);
07407 }
07408
07409
07410
07411
07412 isc_result_t
07413 ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t **text) {
07414 isc_result_t result;
07415 dns_zone_t *zone = NULL;
07416 dns_zonetype_t type;
07417 const char *msg = NULL;
07418
07419 result = zone_from_args(server, args, NULL, &zone, NULL,
07420 text, ISC_TRUE);
07421 if (result != ISC_R_SUCCESS)
07422 return (result);
07423 if (zone == NULL) {
07424 result = reload(server);
07425 if (result == ISC_R_SUCCESS)
07426 msg = "server reload successful";
07427 } else {
07428 type = dns_zone_gettype(zone);
07429 if (type == dns_zone_slave || type == dns_zone_stub) {
07430 dns_zone_refresh(zone);
07431 dns_zone_detach(&zone);
07432 msg = "zone refresh queued";
07433 } else {
07434 result = dns_zone_load(zone);
07435 dns_zone_detach(&zone);
07436 switch (result) {
07437 case ISC_R_SUCCESS:
07438 msg = "zone reload successful";
07439 break;
07440 case DNS_R_CONTINUE:
07441 msg = "zone reload queued";
07442 result = ISC_R_SUCCESS;
07443 break;
07444 case DNS_R_UPTODATE:
07445 msg = "zone reload up-to-date";
07446 result = ISC_R_SUCCESS;
07447 break;
07448 default:
07449
07450 break;
07451 }
07452 }
07453 }
07454 if (msg != NULL) {
07455 (void) putstr(text, msg);
07456 (void) putnull(text);
07457 }
07458 return (result);
07459 }
07460
07461
07462
07463
07464 isc_result_t
07465 ns_server_reconfigcommand(ns_server_t *server, char *args) {
07466 UNUSED(args);
07467
07468 reconfig(server);
07469 return (ISC_R_SUCCESS);
07470 }
07471
07472
07473
07474
07475 isc_result_t
07476 ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text) {
07477 isc_result_t result;
07478 dns_zone_t *zone = NULL;
07479 const char msg[] = "zone notify queued";
07480
07481 result = zone_from_args(server, args, NULL, &zone, NULL,
07482 text, ISC_TRUE);
07483 if (result != ISC_R_SUCCESS)
07484 return (result);
07485 if (zone == NULL)
07486 return (ISC_R_UNEXPECTEDEND);
07487
07488 dns_zone_notify(zone);
07489 dns_zone_detach(&zone);
07490 (void) putstr(text, msg);
07491 (void) putnull(text);
07492
07493 return (ISC_R_SUCCESS);
07494 }
07495
07496
07497
07498
07499 isc_result_t
07500 ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text)
07501 {
07502 isc_result_t result;
07503 dns_zone_t *zone = NULL, *raw = NULL;
07504 const char msg1[] = "zone refresh queued";
07505 const char msg2[] = "not a slave or stub zone";
07506 dns_zonetype_t type;
07507
07508 result = zone_from_args(server, args, NULL, &zone, NULL,
07509 text, ISC_TRUE);
07510 if (result != ISC_R_SUCCESS)
07511 return (result);
07512 if (zone == NULL)
07513 return (ISC_R_UNEXPECTEDEND);
07514
07515 dns_zone_getraw(zone, &raw);
07516 if (raw != NULL) {
07517 dns_zone_detach(&zone);
07518 dns_zone_attach(raw, &zone);
07519 dns_zone_detach(&raw);
07520 }
07521
07522 type = dns_zone_gettype(zone);
07523 if (type == dns_zone_slave || type == dns_zone_stub) {
07524 dns_zone_refresh(zone);
07525 dns_zone_detach(&zone);
07526 (void) putstr(text, msg1);
07527 (void) putnull(text);
07528 return (ISC_R_SUCCESS);
07529 }
07530
07531 dns_zone_detach(&zone);
07532 (void) putstr(text, msg2);
07533 (void) putnull(text);
07534 return (ISC_R_FAILURE);
07535 }
07536
07537 isc_result_t
07538 ns_server_togglequerylog(ns_server_t *server, char *args) {
07539 isc_boolean_t value;
07540 char *ptr;
07541
07542
07543 ptr = next_token(&args, " \t");
07544 if (ptr == NULL)
07545 return (ISC_R_UNEXPECTEDEND);
07546
07547 ptr = next_token(&args, " \t");
07548 if (ptr == NULL)
07549 value = server->log_queries ? ISC_FALSE : ISC_TRUE;
07550 else if (strcasecmp(ptr, "yes") == 0 || strcasecmp(ptr, "on") == 0)
07551 value = ISC_TRUE;
07552 else if (strcasecmp(ptr, "no") == 0 || strcasecmp(ptr, "off") == 0)
07553 value = ISC_FALSE;
07554 else
07555 return (ISC_R_NOTFOUND);
07556
07557 if (server->log_queries == value)
07558 return (ISC_R_SUCCESS);
07559
07560 server->log_queries = value;
07561
07562 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07563 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07564 "query logging is now %s",
07565 server->log_queries ? "on" : "off");
07566 return (ISC_R_SUCCESS);
07567 }
07568
07569 static isc_result_t
07570 ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
07571 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
07572 isc_uint16_t family, ns_listenlist_t **target)
07573 {
07574 isc_result_t result;
07575 const cfg_listelt_t *element;
07576 ns_listenlist_t *dlist = NULL;
07577
07578 REQUIRE(target != NULL && *target == NULL);
07579
07580 result = ns_listenlist_create(mctx, &dlist);
07581 if (result != ISC_R_SUCCESS)
07582 return (result);
07583
07584 for (element = cfg_list_first(listenlist);
07585 element != NULL;
07586 element = cfg_list_next(element))
07587 {
07588 ns_listenelt_t *delt = NULL;
07589 const cfg_obj_t *listener = cfg_listelt_value(element);
07590 result = ns_listenelt_fromconfig(listener, config, actx,
07591 mctx, family, &delt);
07592 if (result != ISC_R_SUCCESS)
07593 goto cleanup;
07594 ISC_LIST_APPEND(dlist->elts, delt, link);
07595 }
07596 *target = dlist;
07597 return (ISC_R_SUCCESS);
07598
07599 cleanup:
07600 ns_listenlist_detach(&dlist);
07601 return (result);
07602 }
07603
07604
07605
07606
07607
07608 static isc_result_t
07609 ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
07610 cfg_aclconfctx_t *actx, isc_mem_t *mctx,
07611 isc_uint16_t family, ns_listenelt_t **target)
07612 {
07613 isc_result_t result;
07614 const cfg_obj_t *portobj, *dscpobj;
07615 in_port_t port;
07616 isc_dscp_t dscp = -1;
07617 ns_listenelt_t *delt = NULL;
07618 REQUIRE(target != NULL && *target == NULL);
07619
07620 portobj = cfg_tuple_get(listener, "port");
07621 if (!cfg_obj_isuint32(portobj)) {
07622 if (ns_g_port != 0) {
07623 port = ns_g_port;
07624 } else {
07625 result = ns_config_getport(config, &port);
07626 if (result != ISC_R_SUCCESS)
07627 return (result);
07628 }
07629 } else {
07630 if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
07631 cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
07632 "port value '%u' is out of range",
07633 cfg_obj_asuint32(portobj));
07634 return (ISC_R_RANGE);
07635 }
07636 port = (in_port_t)cfg_obj_asuint32(portobj);
07637 }
07638
07639 dscpobj = cfg_tuple_get(listener, "dscp");
07640 if (!cfg_obj_isuint32(dscpobj))
07641 dscp = ns_g_dscp;
07642 else {
07643 if (cfg_obj_asuint32(dscpobj) > 63) {
07644 cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
07645 "dscp value '%u' is out of range",
07646 cfg_obj_asuint32(dscpobj));
07647 return (ISC_R_RANGE);
07648 }
07649 dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
07650 }
07651
07652 result = ns_listenelt_create(mctx, port, dscp, NULL, &delt);
07653 if (result != ISC_R_SUCCESS)
07654 return (result);
07655
07656 result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"),
07657 config, ns_g_lctx, actx, mctx, 0,
07658 family, &delt->acl);
07659 if (result != ISC_R_SUCCESS) {
07660 ns_listenelt_destroy(delt);
07661 return (result);
07662 }
07663 *target = delt;
07664 return (ISC_R_SUCCESS);
07665 }
07666
07667 isc_result_t
07668 ns_server_dumpstats(ns_server_t *server) {
07669 isc_result_t result;
07670 FILE *fp = NULL;
07671
07672 CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
07673 "could not open statistics dump file", server->statsfile);
07674
07675 result = ns_stats_dump(server, fp);
07676
07677 cleanup:
07678 if (fp != NULL)
07679 (void)isc_stdio_close(fp);
07680 if (result == ISC_R_SUCCESS)
07681 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07682 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07683 "dumpstats complete");
07684 else
07685 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07686 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
07687 "dumpstats failed: %s",
07688 dns_result_totext(result));
07689 return (result);
07690 }
07691
07692 static isc_result_t
07693 add_zone_tolist(dns_zone_t *zone, void *uap) {
07694 struct dumpcontext *dctx = uap;
07695 struct zonelistentry *zle;
07696
07697 zle = isc_mem_get(dctx->mctx, sizeof *zle);
07698 if (zle == NULL)
07699 return (ISC_R_NOMEMORY);
07700 zle->zone = NULL;
07701 dns_zone_attach(zone, &zle->zone);
07702 ISC_LINK_INIT(zle, link);
07703 ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
07704 return (ISC_R_SUCCESS);
07705 }
07706
07707 static isc_result_t
07708 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
07709 struct viewlistentry *vle;
07710 isc_result_t result = ISC_R_SUCCESS;
07711
07712
07713
07714
07715 for (vle = ISC_LIST_HEAD(dctx->viewlist);
07716 vle != NULL;
07717 vle = ISC_LIST_NEXT(vle, link))
07718 if (vle->view == view)
07719 return (ISC_R_SUCCESS);
07720
07721 vle = isc_mem_get(dctx->mctx, sizeof *vle);
07722 if (vle == NULL)
07723 return (ISC_R_NOMEMORY);
07724 vle->view = NULL;
07725 dns_view_attach(view, &vle->view);
07726 ISC_LINK_INIT(vle, link);
07727 ISC_LIST_INIT(vle->zonelist);
07728 ISC_LIST_APPEND(dctx->viewlist, vle, link);
07729 if (dctx->dumpzones)
07730 result = dns_zt_apply(view->zonetable, ISC_TRUE,
07731 add_zone_tolist, dctx);
07732 return (result);
07733 }
07734
07735 static void
07736 dumpcontext_destroy(struct dumpcontext *dctx) {
07737 struct viewlistentry *vle;
07738 struct zonelistentry *zle;
07739
07740 vle = ISC_LIST_HEAD(dctx->viewlist);
07741 while (vle != NULL) {
07742 ISC_LIST_UNLINK(dctx->viewlist, vle, link);
07743 zle = ISC_LIST_HEAD(vle->zonelist);
07744 while (zle != NULL) {
07745 ISC_LIST_UNLINK(vle->zonelist, zle, link);
07746 dns_zone_detach(&zle->zone);
07747 isc_mem_put(dctx->mctx, zle, sizeof *zle);
07748 zle = ISC_LIST_HEAD(vle->zonelist);
07749 }
07750 dns_view_detach(&vle->view);
07751 isc_mem_put(dctx->mctx, vle, sizeof *vle);
07752 vle = ISC_LIST_HEAD(dctx->viewlist);
07753 }
07754 if (dctx->version != NULL)
07755 dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
07756 if (dctx->db != NULL)
07757 dns_db_detach(&dctx->db);
07758 if (dctx->cache != NULL)
07759 dns_db_detach(&dctx->cache);
07760 if (dctx->task != NULL)
07761 isc_task_detach(&dctx->task);
07762 if (dctx->fp != NULL)
07763 (void)isc_stdio_close(dctx->fp);
07764 if (dctx->mdctx != NULL)
07765 dns_dumpctx_detach(&dctx->mdctx);
07766 isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
07767 }
07768
07769 static void
07770 dumpdone(void *arg, isc_result_t result) {
07771 struct dumpcontext *dctx = arg;
07772 char buf[1024+32];
07773 const dns_master_style_t *style;
07774
07775 if (result != ISC_R_SUCCESS)
07776 goto cleanup;
07777 if (dctx->mdctx != NULL)
07778 dns_dumpctx_detach(&dctx->mdctx);
07779 if (dctx->view == NULL) {
07780 dctx->view = ISC_LIST_HEAD(dctx->viewlist);
07781 if (dctx->view == NULL)
07782 goto done;
07783 INSIST(dctx->zone == NULL);
07784 } else
07785 goto resume;
07786 nextview:
07787 fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
07788 resume:
07789 if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) {
07790 fprintf(dctx->fp,
07791 ";\n; Cache of view '%s' is shared as '%s'\n",
07792 dctx->view->view->name,
07793 dns_cache_getname(dctx->view->view->cache));
07794 } else if (dctx->zone == NULL && dctx->cache == NULL &&
07795 dctx->dumpcache)
07796 {
07797 style = &dns_master_style_cache;
07798
07799 if (dctx->view->view->cachedb != NULL)
07800 dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
07801 if (dctx->cache != NULL) {
07802 fprintf(dctx->fp,
07803 ";\n; Cache dump of view '%s' (cache %s)\n;\n",
07804 dctx->view->view->name,
07805 dns_cache_getname(dctx->view->view->cache));
07806 result = dns_master_dumptostreaminc(dctx->mctx,
07807 dctx->cache, NULL,
07808 style, dctx->fp,
07809 dctx->task,
07810 dumpdone, dctx,
07811 &dctx->mdctx);
07812 if (result == DNS_R_CONTINUE)
07813 return;
07814 if (result == ISC_R_NOTIMPLEMENTED)
07815 fprintf(dctx->fp, "; %s\n",
07816 dns_result_totext(result));
07817 else if (result != ISC_R_SUCCESS)
07818 goto cleanup;
07819 }
07820 }
07821 if (dctx->cache != NULL) {
07822 dns_adb_dump(dctx->view->view->adb, dctx->fp);
07823 dns_resolver_printbadcache(dctx->view->view->resolver,
07824 dctx->fp);
07825 dns_badcache_print(dctx->view->view->failcache,
07826 "SERVFAIL cache", dctx->fp);
07827 dns_db_detach(&dctx->cache);
07828 }
07829 if (dctx->dumpzones) {
07830 style = &dns_master_style_full;
07831 nextzone:
07832 if (dctx->version != NULL)
07833 dns_db_closeversion(dctx->db, &dctx->version,
07834 ISC_FALSE);
07835 if (dctx->db != NULL)
07836 dns_db_detach(&dctx->db);
07837 if (dctx->zone == NULL)
07838 dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
07839 else
07840 dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
07841 if (dctx->zone != NULL) {
07842
07843 dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
07844 fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
07845 result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
07846 if (result != ISC_R_SUCCESS) {
07847 fprintf(dctx->fp, "; %s\n",
07848 dns_result_totext(result));
07849 goto nextzone;
07850 }
07851 dns_db_currentversion(dctx->db, &dctx->version);
07852 result = dns_master_dumptostreaminc(dctx->mctx,
07853 dctx->db,
07854 dctx->version,
07855 style, dctx->fp,
07856 dctx->task,
07857 dumpdone, dctx,
07858 &dctx->mdctx);
07859 if (result == DNS_R_CONTINUE)
07860 return;
07861 if (result == ISC_R_NOTIMPLEMENTED) {
07862 fprintf(dctx->fp, "; %s\n",
07863 dns_result_totext(result));
07864 result = ISC_R_SUCCESS;
07865 POST(result);
07866 goto nextzone;
07867 }
07868 if (result != ISC_R_SUCCESS)
07869 goto cleanup;
07870 }
07871 }
07872 if (dctx->view != NULL)
07873 dctx->view = ISC_LIST_NEXT(dctx->view, link);
07874 if (dctx->view != NULL)
07875 goto nextview;
07876 done:
07877 fprintf(dctx->fp, "; Dump complete\n");
07878 result = isc_stdio_flush(dctx->fp);
07879 if (result == ISC_R_SUCCESS)
07880 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07881 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07882 "dumpdb complete");
07883 cleanup:
07884 if (result != ISC_R_SUCCESS)
07885 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07886 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
07887 "dumpdb failed: %s", dns_result_totext(result));
07888 dumpcontext_destroy(dctx);
07889 }
07890
07891 isc_result_t
07892 ns_server_dumpdb(ns_server_t *server, char *args) {
07893 struct dumpcontext *dctx = NULL;
07894 dns_view_t *view;
07895 isc_result_t result;
07896 char *ptr;
07897 const char *sep;
07898
07899
07900 ptr = next_token(&args, " \t");
07901 if (ptr == NULL)
07902 return (ISC_R_UNEXPECTEDEND);
07903
07904 dctx = isc_mem_get(server->mctx, sizeof(*dctx));
07905 if (dctx == NULL)
07906 return (ISC_R_NOMEMORY);
07907
07908 dctx->mctx = server->mctx;
07909 dctx->dumpcache = ISC_TRUE;
07910 dctx->dumpzones = ISC_FALSE;
07911 dctx->fp = NULL;
07912 ISC_LIST_INIT(dctx->viewlist);
07913 dctx->view = NULL;
07914 dctx->zone = NULL;
07915 dctx->cache = NULL;
07916 dctx->mdctx = NULL;
07917 dctx->db = NULL;
07918 dctx->cache = NULL;
07919 dctx->task = NULL;
07920 dctx->version = NULL;
07921 isc_task_attach(server->task, &dctx->task);
07922
07923 CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
07924 "could not open dump file", server->dumpfile);
07925
07926 sep = (args == NULL) ? "" : ": ";
07927 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
07928 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
07929 "dumpdb started%s%s", sep, (args != NULL) ? args : "");
07930
07931 ptr = next_token(&args, " \t");
07932 if (ptr != NULL && strcmp(ptr, "-all") == 0) {
07933 dctx->dumpzones = ISC_TRUE;
07934 dctx->dumpcache = ISC_TRUE;
07935 ptr = next_token(&args, " \t");
07936 } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
07937 dctx->dumpzones = ISC_FALSE;
07938 dctx->dumpcache = ISC_TRUE;
07939 ptr = next_token(&args, " \t");
07940 } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
07941 dctx->dumpzones = ISC_TRUE;
07942 dctx->dumpcache = ISC_FALSE;
07943 ptr = next_token(&args, " \t");
07944 }
07945
07946 nextview:
07947 for (view = ISC_LIST_HEAD(server->viewlist);
07948 view != NULL;
07949 view = ISC_LIST_NEXT(view, link))
07950 {
07951 if (ptr != NULL && strcmp(view->name, ptr) != 0)
07952 continue;
07953 CHECK(add_view_tolist(dctx, view));
07954 }
07955 if (ptr != NULL) {
07956 ptr = next_token(&args, " \t");
07957 if (ptr != NULL)
07958 goto nextview;
07959 }
07960 dumpdone(dctx, ISC_R_SUCCESS);
07961 return (ISC_R_SUCCESS);
07962
07963 cleanup:
07964 if (dctx != NULL)
07965 dumpcontext_destroy(dctx);
07966 return (result);
07967 }
07968
07969 isc_result_t
07970 ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text) {
07971 dns_view_t *view;
07972 dns_keytable_t *secroots = NULL;
07973 dns_ntatable_t *ntatable = NULL;
07974 isc_result_t result;
07975 char *ptr;
07976 FILE *fp = NULL;
07977 isc_time_t now;
07978 char tbuf[64];
07979
07980
07981 ptr = next_token(&args, " \t");
07982 if (ptr == NULL)
07983 return (ISC_R_UNEXPECTEDEND);
07984
07985
07986 ptr = next_token(&args, " \t");
07987 if (ptr != NULL && strcmp(ptr, "-") == 0)
07988 ptr = next_token(&args, " \t");
07989 else {
07990 result = isc_stdio_open(server->secrootsfile, "w", &fp);
07991 if (result != ISC_R_SUCCESS) {
07992 (void) putstr(text, "could not open ");
07993 (void) putstr(text, server->secrootsfile);
07994 CHECKMF(result, "could not open secroots dump file",
07995 server->secrootsfile);
07996 }
07997 }
07998
07999 TIME_NOW(&now);
08000 isc_time_formattimestamp(&now, tbuf, sizeof(tbuf));
08001 CHECK(putstr(text, "secure roots as of "));
08002 CHECK(putstr(text, tbuf));
08003 CHECK(putstr(text, ":\n"));
08004
08005 do {
08006 for (view = ISC_LIST_HEAD(server->viewlist);
08007 view != NULL;
08008 view = ISC_LIST_NEXT(view, link))
08009 {
08010 if (ptr != NULL && strcmp(view->name, ptr) != 0)
08011 continue;
08012 if (secroots != NULL)
08013 dns_keytable_detach(&secroots);
08014 result = dns_view_getsecroots(view, &secroots);
08015 if (result == ISC_R_NOTFOUND) {
08016 result = ISC_R_SUCCESS;
08017 continue;
08018 }
08019 CHECK(putstr(text, "\n Start view "));
08020 CHECK(putstr(text, view->name));
08021 CHECK(putstr(text, "\n Secure roots:\n\n"));
08022 CHECK(dns_keytable_totext(secroots, text));
08023
08024 if (ntatable != NULL)
08025 dns_ntatable_detach(&ntatable);
08026 result = dns_view_getntatable(view, &ntatable);
08027 if (result == ISC_R_NOTFOUND) {
08028 result = ISC_R_SUCCESS;
08029 continue;
08030 }
08031 CHECK(putstr(text, "\n Negative trust anchors:\n\n"));
08032 CHECK(dns_ntatable_totext(ntatable, text));
08033 }
08034 if (ptr != NULL)
08035 ptr = next_token(&args, " \t");
08036 } while (ptr != NULL);
08037
08038 cleanup:
08039 if (isc_buffer_usedlength(*text) > 0) {
08040 if (fp != NULL)
08041 (void)putstr(text, "\n");
08042 else
08043 (void)putnull(text);
08044 }
08045 if (secroots != NULL)
08046 dns_keytable_detach(&secroots);
08047 if (ntatable != NULL)
08048 dns_ntatable_detach(&ntatable);
08049 if (fp != NULL) {
08050 fprintf(fp, "%.*s", (int) isc_buffer_usedlength(*text),
08051 (char *) isc_buffer_base(*text));
08052 isc_buffer_clear(*text);
08053 (void)isc_stdio_close(fp);
08054 }
08055 if (result == ISC_R_SUCCESS)
08056 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08057 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08058 "dumpsecroots complete");
08059 else
08060 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08061 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08062 "dumpsecroots failed: %s",
08063 dns_result_totext(result));
08064 return (result);
08065 }
08066
08067 isc_result_t
08068 ns_server_dumprecursing(ns_server_t *server) {
08069 FILE *fp = NULL;
08070 isc_result_t result;
08071
08072 CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
08073 "could not open dump file", server->recfile);
08074 fprintf(fp,";\n; Recursing Queries\n;\n");
08075 ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
08076 fprintf(fp, "; Dump complete\n");
08077
08078 cleanup:
08079 if (fp != NULL)
08080 result = isc_stdio_close(fp);
08081 if (result == ISC_R_SUCCESS)
08082 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08083 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08084 "dumprecursing complete");
08085 else
08086 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08087 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08088 "dumprecursing failed: %s",
08089 dns_result_totext(result));
08090 return (result);
08091 }
08092
08093 isc_result_t
08094 ns_server_setdebuglevel(ns_server_t *server, char *args) {
08095 char *ptr;
08096 char *levelstr;
08097 char *endp;
08098 long newlevel;
08099
08100 UNUSED(server);
08101
08102
08103 ptr = next_token(&args, " \t");
08104 if (ptr == NULL)
08105 return (ISC_R_UNEXPECTEDEND);
08106
08107
08108 levelstr = next_token(&args, " \t");
08109 if (levelstr == NULL) {
08110 if (ns_g_debuglevel < 99)
08111 ns_g_debuglevel++;
08112 } else {
08113 newlevel = strtol(levelstr, &endp, 10);
08114 if (*endp != '\0' || newlevel < 0 || newlevel > 99)
08115 return (ISC_R_RANGE);
08116 ns_g_debuglevel = (unsigned int)newlevel;
08117 }
08118 isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
08119 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08120 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08121 "debug level is now %d", ns_g_debuglevel);
08122 return (ISC_R_SUCCESS);
08123 }
08124
08125 isc_result_t
08126 ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text) {
08127 char *ptr, *viewname;
08128 dns_view_t *view;
08129 isc_boolean_t changed = ISC_FALSE;
08130 isc_result_t result;
08131 isc_boolean_t enable = ISC_TRUE, set = ISC_TRUE, first = ISC_TRUE;
08132
08133
08134 ptr = next_token(&args, " \t");
08135 if (ptr == NULL)
08136 return (ISC_R_UNEXPECTEDEND);
08137
08138
08139 ptr = next_token(&args, " \t");
08140 if (ptr == NULL)
08141 return (ISC_R_UNEXPECTEDEND);
08142
08143 if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
08144 !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
08145 enable = ISC_TRUE;
08146 else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
08147 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
08148 enable = ISC_FALSE;
08149 else if (!strcasecmp(ptr, "check"))
08150 set = ISC_FALSE;
08151 else
08152 return (DNS_R_SYNTAX);
08153
08154
08155 viewname = next_token(&args, " \t");
08156
08157 result = isc_task_beginexclusive(server->task);
08158 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08159 for (view = ISC_LIST_HEAD(server->viewlist);
08160 view != NULL;
08161 view = ISC_LIST_NEXT(view, link))
08162 {
08163 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
08164 continue;
08165 CHECK(dns_view_flushcache(view));
08166
08167 if (set) {
08168 view->enablevalidation = enable;
08169 changed = ISC_TRUE;
08170 } else {
08171 if (!first)
08172 CHECK(putstr(text, "\n"));
08173 CHECK(putstr(text, "DNSSEC validation is "));
08174 CHECK(putstr(text, view->enablevalidation
08175 ? "enabled" : "disabled"));
08176 CHECK(putstr(text, " (view "));
08177 CHECK(putstr(text, view->name));
08178 CHECK(putstr(text, ")"));
08179 CHECK(putnull(text));
08180 first = ISC_FALSE;
08181 }
08182 }
08183
08184 if (!set)
08185 result = ISC_R_SUCCESS;
08186 else if (changed)
08187 result = ISC_R_SUCCESS;
08188 else
08189 result = ISC_R_FAILURE;
08190 cleanup:
08191 isc_task_endexclusive(server->task);
08192 return (result);
08193 }
08194
08195 isc_result_t
08196 ns_server_flushcache(ns_server_t *server, char *args) {
08197 char *ptr, *viewname;
08198 dns_view_t *view;
08199 isc_boolean_t flushed;
08200 isc_boolean_t found;
08201 isc_result_t result;
08202 ns_cache_t *nsc;
08203
08204
08205 ptr = next_token(&args, " \t");
08206 if (ptr == NULL)
08207 return (ISC_R_UNEXPECTEDEND);
08208
08209
08210 viewname = next_token(&args, " \t");
08211
08212 result = isc_task_beginexclusive(server->task);
08213 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08214 flushed = ISC_TRUE;
08215 found = ISC_FALSE;
08216
08217
08218
08219
08220
08221
08222
08223 if (viewname != NULL) {
08224
08225
08226
08227
08228
08229
08230 for (view = ISC_LIST_HEAD(server->viewlist);
08231 view != NULL;
08232 view = ISC_LIST_NEXT(view, link))
08233 {
08234 if (strcasecmp(viewname, view->name) != 0)
08235 continue;
08236 found = ISC_TRUE;
08237 for (nsc = ISC_LIST_HEAD(server->cachelist);
08238 nsc != NULL;
08239 nsc = ISC_LIST_NEXT(nsc, link)) {
08240 if (nsc->cache == view->cache)
08241 break;
08242 }
08243 INSIST(nsc != NULL);
08244 nsc->needflush = ISC_TRUE;
08245 }
08246 } else
08247 found = ISC_TRUE;
08248
08249
08250 for (nsc = ISC_LIST_HEAD(server->cachelist);
08251 nsc != NULL;
08252 nsc = ISC_LIST_NEXT(nsc, link)) {
08253 if (viewname != NULL && !nsc->needflush)
08254 continue;
08255 nsc->needflush = ISC_TRUE;
08256 result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE);
08257 if (result != ISC_R_SUCCESS) {
08258 flushed = ISC_FALSE;
08259 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08260 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08261 "flushing cache in view '%s' failed: %s",
08262 nsc->primaryview->name,
08263 isc_result_totext(result));
08264 }
08265 }
08266
08267
08268
08269
08270
08271
08272
08273
08274
08275
08276 for (view = ISC_LIST_HEAD(server->viewlist);
08277 view != NULL;
08278 view = ISC_LIST_NEXT(view, link))
08279 {
08280 if (!dns_view_iscacheshared(view))
08281 continue;
08282 for (nsc = ISC_LIST_HEAD(server->cachelist);
08283 nsc != NULL;
08284 nsc = ISC_LIST_NEXT(nsc, link)) {
08285 if (!nsc->needflush || nsc->cache != view->cache)
08286 continue;
08287 result = dns_view_flushcache2(view, ISC_TRUE);
08288 if (result != ISC_R_SUCCESS) {
08289 flushed = ISC_FALSE;
08290 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08291 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08292 "fixing cache in view '%s' "
08293 "failed: %s", view->name,
08294 isc_result_totext(result));
08295 }
08296 }
08297 }
08298
08299
08300 for (nsc = ISC_LIST_HEAD(server->cachelist);
08301 nsc != NULL;
08302 nsc = ISC_LIST_NEXT(nsc, link)) {
08303 nsc->needflush = ISC_FALSE;
08304 }
08305
08306 if (flushed && found) {
08307 if (viewname != NULL)
08308 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08309 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08310 "flushing cache in view '%s' succeeded",
08311 viewname);
08312 else
08313 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08314 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08315 "flushing caches in all views succeeded");
08316 result = ISC_R_SUCCESS;
08317 } else {
08318 if (!found) {
08319 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08320 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08321 "flushing cache in view '%s' failed: "
08322 "view not found", viewname);
08323 result = ISC_R_NOTFOUND;
08324 } else
08325 result = ISC_R_FAILURE;
08326 }
08327 isc_task_endexclusive(server->task);
08328 return (result);
08329 }
08330
08331 isc_result_t
08332 ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) {
08333 char *target, *viewname;
08334 dns_view_t *view;
08335 isc_boolean_t flushed;
08336 isc_boolean_t found;
08337 isc_result_t result;
08338 isc_buffer_t b;
08339 dns_fixedname_t fixed;
08340 dns_name_t *name;
08341
08342
08343 target = next_token(&args, " \t");
08344 if (target == NULL)
08345 return (ISC_R_UNEXPECTEDEND);
08346
08347
08348 target = next_token(&args, " \t");
08349 if (target == NULL)
08350 return (ISC_R_UNEXPECTEDEND);
08351
08352 isc_buffer_constinit(&b, target, strlen(target));
08353 isc_buffer_add(&b, strlen(target));
08354 dns_fixedname_init(&fixed);
08355 name = dns_fixedname_name(&fixed);
08356 result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
08357 if (result != ISC_R_SUCCESS)
08358 return (result);
08359
08360
08361 viewname = next_token(&args, " \t");
08362
08363 result = isc_task_beginexclusive(server->task);
08364 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08365 flushed = ISC_TRUE;
08366 found = ISC_FALSE;
08367 for (view = ISC_LIST_HEAD(server->viewlist);
08368 view != NULL;
08369 view = ISC_LIST_NEXT(view, link))
08370 {
08371 if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
08372 continue;
08373 found = ISC_TRUE;
08374
08375
08376
08377
08378
08379 result = dns_view_flushnode(view, name, tree);
08380 if (result != ISC_R_SUCCESS) {
08381 flushed = ISC_FALSE;
08382 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08383 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08384 "flushing %s '%s' in cache view '%s' "
08385 "failed: %s",
08386 tree ? "tree" : "name",
08387 target, view->name,
08388 isc_result_totext(result));
08389 }
08390 }
08391 if (flushed && found) {
08392 if (viewname != NULL)
08393 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08394 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08395 "flushing %s '%s' in cache view '%s' "
08396 "succeeded",
08397 tree ? "tree" : "name",
08398 target, viewname);
08399 else
08400 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08401 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08402 "flushing %s '%s' in all cache views "
08403 "succeeded",
08404 tree ? "tree" : "name",
08405 target);
08406 result = ISC_R_SUCCESS;
08407 } else {
08408 if (!found)
08409 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08410 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
08411 "flushing %s '%s' in cache view '%s' "
08412 "failed: view not found",
08413 tree ? "tree" : "name",
08414 target, viewname);
08415 result = ISC_R_FAILURE;
08416 }
08417 isc_task_endexclusive(server->task);
08418 return (result);
08419 }
08420
08421 isc_result_t
08422 ns_server_status(ns_server_t *server, isc_buffer_t **text) {
08423 isc_result_t result;
08424 unsigned int zonecount, xferrunning, xferdeferred, soaqueries;
08425 unsigned int automatic;
08426 const char *ob = "", *cb = "", *alt = "";
08427 char boottime[ISC_FORMATHTTPTIMESTAMP_SIZE];
08428 char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE];
08429 char line[1024];
08430
08431 if (ns_g_server->version_set) {
08432 ob = " (";
08433 cb = ")";
08434 if (ns_g_server->version == NULL)
08435 alt = "version.bind/txt/ch disabled";
08436 else
08437 alt = ns_g_server->version;
08438 }
08439 zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
08440 xferrunning = dns_zonemgr_getcount(server->zonemgr,
08441 DNS_ZONESTATE_XFERRUNNING);
08442 xferdeferred = dns_zonemgr_getcount(server->zonemgr,
08443 DNS_ZONESTATE_XFERDEFERRED);
08444 soaqueries = dns_zonemgr_getcount(server->zonemgr,
08445 DNS_ZONESTATE_SOAQUERY);
08446 automatic = dns_zonemgr_getcount(server->zonemgr,
08447 DNS_ZONESTATE_AUTOMATIC);
08448
08449 isc_time_formathttptimestamp(&ns_g_boottime, boottime,
08450 sizeof(boottime));
08451 isc_time_formathttptimestamp(&ns_g_configtime, configtime,
08452 sizeof(configtime));
08453
08454 snprintf(line, sizeof(line), "version: %s %s%s%s <id:%s>%s%s%s\n",
08455 ns_g_product, ns_g_version,
08456 (*ns_g_description != '\0') ? " " : "",
08457 ns_g_description, ns_g_srcid, ob, alt, cb);
08458 CHECK(putstr(text, line));
08459
08460 snprintf(line, sizeof(line), "boot time: %s\n", boottime);
08461 CHECK(putstr(text, line));
08462
08463 snprintf(line, sizeof(line), "last configured: %s\n", configtime);
08464 CHECK(putstr(text, line));
08465
08466 #ifdef ISC_PLATFORM_USETHREADS
08467 snprintf(line, sizeof(line), "CPUs found: %u\n", ns_g_cpus_detected);
08468 CHECK(putstr(text, line));
08469
08470 snprintf(line, sizeof(line), "worker threads: %u\n", ns_g_cpus);
08471 CHECK(putstr(text, line));
08472
08473 snprintf(line, sizeof(line), "UDP listeners per interface: %u\n",
08474 ns_g_udpdisp);
08475 CHECK(putstr(text, line));
08476 #else
08477 snprintf(line, sizeof(line), "CPUs found: N/A (threads disabled)\n");
08478 CHECK(putstr(text, line));
08479 #endif
08480
08481 snprintf(line, sizeof(line), "number of zones: %u (%u automatic)\n",
08482 zonecount, automatic);
08483 CHECK(putstr(text, line));
08484
08485 snprintf(line, sizeof(line), "debug level: %d\n", ns_g_debuglevel);
08486 CHECK(putstr(text, line));
08487
08488 snprintf(line, sizeof(line), "xfers running: %u\n", xferrunning);
08489 CHECK(putstr(text, line));
08490
08491 snprintf(line, sizeof(line), "xfers deferred: %u\n", xferdeferred);
08492 CHECK(putstr(text, line));
08493
08494 snprintf(line, sizeof(line), "soa queries in progress: %u\n",
08495 soaqueries);
08496 CHECK(putstr(text, line));
08497
08498 snprintf(line, sizeof(line), "query logging is %s\n",
08499 server->log_queries ? "ON" : "OFF");
08500 CHECK(putstr(text, line));
08501
08502 snprintf(line, sizeof(line), "recursive clients: %d/%d/%d\n",
08503 server->recursionquota.used, server->recursionquota.soft,
08504 server->recursionquota.max);
08505 CHECK(putstr(text, line));
08506
08507 snprintf(line, sizeof(line), "tcp clients: %d/%d\n",
08508 server->tcpquota.used, server->tcpquota.max);
08509 CHECK(putstr(text, line));
08510
08511 CHECK(putstr(text, "server is up and running"));
08512 CHECK(putnull(text));
08513
08514 return (ISC_R_SUCCESS);
08515 cleanup:
08516 return (result);
08517 }
08518
08519 isc_result_t
08520 ns_server_testgen(char *args, isc_buffer_t **text) {
08521 isc_result_t result;
08522 char *ptr;
08523 unsigned long count;
08524 unsigned long i;
08525 const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
08526
08527
08528 ptr = next_token(&args, " \t");
08529 if (ptr == NULL)
08530 return (ISC_R_UNEXPECTEDEND);
08531
08532 ptr = next_token(&args, " \t");
08533 if (ptr == NULL)
08534 count = 26;
08535 else
08536 count = strtoul(ptr, NULL, 10);
08537
08538 CHECK(isc_buffer_reserve(text, count));
08539 for (i = 0; i < count; i++)
08540 CHECK(putuint8(text, chars[i % (sizeof(chars) - 1)]));
08541
08542 CHECK(putnull(text));
08543
08544 cleanup:
08545 return (result);
08546 }
08547
08548 static isc_result_t
08549 delete_keynames(dns_tsig_keyring_t *ring, char *target,
08550 unsigned int *foundkeys)
08551 {
08552 char namestr[DNS_NAME_FORMATSIZE];
08553 isc_result_t result;
08554 dns_rbtnodechain_t chain;
08555 dns_name_t foundname;
08556 dns_fixedname_t fixedorigin;
08557 dns_name_t *origin;
08558 dns_rbtnode_t *node;
08559 dns_tsigkey_t *tkey;
08560
08561 dns_name_init(&foundname, NULL);
08562 dns_fixedname_init(&fixedorigin);
08563 origin = dns_fixedname_name(&fixedorigin);
08564
08565 again:
08566 dns_rbtnodechain_init(&chain, ring->mctx);
08567 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
08568 origin);
08569 if (result == ISC_R_NOTFOUND) {
08570 dns_rbtnodechain_invalidate(&chain);
08571 return (ISC_R_SUCCESS);
08572 }
08573 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
08574 dns_rbtnodechain_invalidate(&chain);
08575 return (result);
08576 }
08577
08578 for (;;) {
08579 node = NULL;
08580 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
08581 tkey = node->data;
08582
08583 if (tkey != NULL) {
08584 if (!tkey->generated)
08585 goto nextkey;
08586
08587 dns_name_format(&tkey->name, namestr, sizeof(namestr));
08588 if (strcmp(namestr, target) == 0) {
08589 (*foundkeys)++;
08590 dns_rbtnodechain_invalidate(&chain);
08591 (void)dns_rbt_deletename(ring->keys,
08592 &tkey->name,
08593 ISC_FALSE);
08594 goto again;
08595 }
08596 }
08597
08598 nextkey:
08599 result = dns_rbtnodechain_next(&chain, &foundname, origin);
08600 if (result == ISC_R_NOMORE)
08601 break;
08602 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
08603 dns_rbtnodechain_invalidate(&chain);
08604 return (result);
08605 }
08606 }
08607
08608 return (ISC_R_SUCCESS);
08609 }
08610
08611 isc_result_t
08612 ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t **text) {
08613 isc_result_t result;
08614 dns_view_t *view;
08615 unsigned int foundkeys = 0;
08616 char *target, *viewname;
08617 char fbuf[16];
08618
08619 (void)next_token(&command, " \t");
08620 target = next_token(&command, " \t");
08621 if (target == NULL)
08622 return (ISC_R_UNEXPECTEDEND);
08623 viewname = next_token(&command, " \t");
08624
08625 result = isc_task_beginexclusive(server->task);
08626 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08627 for (view = ISC_LIST_HEAD(server->viewlist);
08628 view != NULL;
08629 view = ISC_LIST_NEXT(view, link)) {
08630 if (viewname == NULL || strcmp(view->name, viewname) == 0) {
08631 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
08632 result = delete_keynames(view->dynamickeys, target,
08633 &foundkeys);
08634 RWUNLOCK(&view->dynamickeys->lock,
08635 isc_rwlocktype_write);
08636 if (result != ISC_R_SUCCESS) {
08637 isc_task_endexclusive(server->task);
08638 return (result);
08639 }
08640 }
08641 }
08642 isc_task_endexclusive(server->task);
08643
08644 snprintf(fbuf, sizeof(fbuf), "%d", foundkeys);
08645
08646 CHECK(putstr(text, fbuf));
08647 CHECK(putstr(text, " tsig keys deleted."));
08648 CHECK(putnull(text));
08649
08650 cleanup:
08651 return (result);
08652 }
08653
08654 static isc_result_t
08655 list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t **text,
08656 unsigned int *foundkeys)
08657 {
08658 char namestr[DNS_NAME_FORMATSIZE];
08659 char creatorstr[DNS_NAME_FORMATSIZE];
08660 isc_result_t result;
08661 dns_rbtnodechain_t chain;
08662 dns_name_t foundname;
08663 dns_fixedname_t fixedorigin;
08664 dns_name_t *origin;
08665 dns_rbtnode_t *node;
08666 dns_tsigkey_t *tkey;
08667 const char *viewname;
08668
08669 if (view != NULL)
08670 viewname = view->name;
08671 else
08672 viewname = "(global)";
08673
08674 dns_name_init(&foundname, NULL);
08675 dns_fixedname_init(&fixedorigin);
08676 origin = dns_fixedname_name(&fixedorigin);
08677 dns_rbtnodechain_init(&chain, ring->mctx);
08678 result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
08679 origin);
08680 if (result == ISC_R_NOTFOUND) {
08681 dns_rbtnodechain_invalidate(&chain);
08682 return (ISC_R_SUCCESS);
08683 }
08684 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
08685 dns_rbtnodechain_invalidate(&chain);
08686 return (result);
08687 }
08688
08689 for (;;) {
08690 node = NULL;
08691 dns_rbtnodechain_current(&chain, &foundname, origin, &node);
08692 tkey = node->data;
08693
08694 if (tkey != NULL) {
08695 dns_name_format(&tkey->name, namestr, sizeof(namestr));
08696 if (tkey->generated) {
08697 dns_name_format(tkey->creator, creatorstr,
08698 sizeof(creatorstr));
08699 if (*foundkeys != 0)
08700 CHECK(putstr(text, "\n"));
08701 CHECK(putstr(text, "view \""));
08702 CHECK(putstr(text, viewname));
08703 CHECK(putstr(text,
08704 "\"; type \"dynamic\"; key \""));
08705 CHECK(putstr(text, namestr));
08706 CHECK(putstr(text, "\"; creator \""));
08707 CHECK(putstr(text, creatorstr));
08708 CHECK(putstr(text, "\";"));
08709 } else {
08710 if (*foundkeys != 0)
08711 CHECK(putstr(text, "\n"));
08712 CHECK(putstr(text, "view \""));
08713 CHECK(putstr(text, viewname));
08714 CHECK(putstr(text,
08715 "\"; type \"static\"; key \""));
08716 CHECK(putstr(text, namestr));
08717 CHECK(putstr(text, "\";"));
08718 }
08719 (*foundkeys)++;
08720 }
08721 result = dns_rbtnodechain_next(&chain, &foundname, origin);
08722 if (result == ISC_R_NOMORE || result == DNS_R_NEWORIGIN)
08723 break;
08724 }
08725
08726 return (ISC_R_SUCCESS);
08727 cleanup:
08728 dns_rbtnodechain_invalidate(&chain);
08729 return (result);
08730 }
08731
08732 isc_result_t
08733 ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text) {
08734 isc_result_t result;
08735 dns_view_t *view;
08736 unsigned int foundkeys = 0;
08737
08738 result = isc_task_beginexclusive(server->task);
08739 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08740 for (view = ISC_LIST_HEAD(server->viewlist);
08741 view != NULL;
08742 view = ISC_LIST_NEXT(view, link)) {
08743 RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
08744 result = list_keynames(view, view->statickeys, text,
08745 &foundkeys);
08746 RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
08747 if (result != ISC_R_SUCCESS) {
08748 isc_task_endexclusive(server->task);
08749 return (result);
08750 }
08751 RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
08752 result = list_keynames(view, view->dynamickeys, text,
08753 &foundkeys);
08754 RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
08755 if (result != ISC_R_SUCCESS) {
08756 isc_task_endexclusive(server->task);
08757 return (result);
08758 }
08759 }
08760 isc_task_endexclusive(server->task);
08761
08762 if (foundkeys == 0)
08763 CHECK(putstr(text, "no tsig keys found."));
08764
08765 if (isc_buffer_usedlength(*text) > 0)
08766 CHECK(putnull(text));
08767
08768 cleanup:
08769 return (result);
08770 }
08771
08772
08773
08774
08775 isc_result_t
08776 ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t **text) {
08777 isc_result_t result;
08778 dns_zone_t *zone = NULL;
08779 dns_zonetype_t type;
08780 isc_uint16_t keyopts;
08781 isc_boolean_t fullsign = ISC_FALSE;
08782
08783 if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0)
08784 fullsign = ISC_TRUE;
08785
08786 result = zone_from_args(server, args, NULL, &zone, NULL,
08787 text, ISC_TRUE);
08788 if (result != ISC_R_SUCCESS)
08789 return (result);
08790 if (zone == NULL)
08791 return (ISC_R_UNEXPECTEDEND);
08792
08793 type = dns_zone_gettype(zone);
08794 if (type != dns_zone_master) {
08795 dns_zone_detach(&zone);
08796 return (DNS_R_NOTMASTER);
08797 }
08798
08799 keyopts = dns_zone_getkeyopts(zone);
08800
08801
08802 if ((keyopts & DNS_ZONEKEY_ALLOW) == 0)
08803 result = ISC_R_NOPERM;
08804 else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign)
08805 result = ISC_R_NOPERM;
08806 else
08807 dns_zone_rekey(zone, fullsign);
08808
08809 dns_zone_detach(&zone);
08810 return (result);
08811 }
08812
08813
08814
08815
08816 static isc_result_t
08817 synczone(dns_zone_t *zone, void *uap) {
08818 isc_boolean_t cleanup = *(isc_boolean_t *)uap;
08819 isc_result_t result;
08820 dns_zone_t *raw = NULL;
08821 char *journal;
08822
08823 dns_zone_getraw(zone, &raw);
08824 if (raw != NULL) {
08825 synczone(raw, uap);
08826 dns_zone_detach(&raw);
08827 }
08828
08829 result = dns_zone_flush(zone);
08830 if (result != ISC_R_SUCCESS)
08831 cleanup = ISC_FALSE;
08832 if (cleanup) {
08833 journal = dns_zone_getjournal(zone);
08834 if (journal != NULL)
08835 (void)isc_file_remove(journal);
08836 }
08837
08838 return (result);
08839 }
08840
08841 isc_result_t
08842 ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text) {
08843 isc_result_t result, tresult;
08844 dns_view_t *view;
08845 dns_zone_t *zone = NULL;
08846 char classstr[DNS_RDATACLASS_FORMATSIZE];
08847 char zonename[DNS_NAME_FORMATSIZE];
08848 const char *vname, *sep, *arg;
08849 isc_boolean_t cleanup = ISC_FALSE;
08850
08851 (void) next_token(&args, " \t");
08852
08853 arg = next_token(&args, " \t");
08854 if (arg != NULL &&
08855 (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) {
08856 cleanup = ISC_TRUE;
08857 arg = next_token(&args, " \t");
08858 }
08859
08860 result = zone_from_args(server, args, arg, &zone, NULL,
08861 text, ISC_FALSE);
08862 if (result != ISC_R_SUCCESS)
08863 return (result);
08864
08865 if (zone == NULL) {
08866 result = isc_task_beginexclusive(server->task);
08867 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08868 tresult = ISC_R_SUCCESS;
08869 for (view = ISC_LIST_HEAD(server->viewlist);
08870 view != NULL;
08871 view = ISC_LIST_NEXT(view, link)) {
08872 result = dns_zt_apply(view->zonetable, ISC_FALSE,
08873 synczone, &cleanup);
08874 if (result != ISC_R_SUCCESS &&
08875 tresult == ISC_R_SUCCESS)
08876 tresult = result;
08877 }
08878 isc_task_endexclusive(server->task);
08879 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08880 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08881 "dumping all zones%s: %s",
08882 cleanup ? ", removing journal files" : "",
08883 isc_result_totext(result));
08884 return (tresult);
08885 }
08886
08887 result = isc_task_beginexclusive(server->task);
08888 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08889 result = synczone(zone, &cleanup);
08890 isc_task_endexclusive(server->task);
08891
08892 view = dns_zone_getview(zone);
08893 if (strcmp(view->name, "_default") == 0 ||
08894 strcmp(view->name, "_bind") == 0)
08895 {
08896 vname = "";
08897 sep = "";
08898 } else {
08899 vname = view->name;
08900 sep = " ";
08901 }
08902 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
08903 sizeof(classstr));
08904 dns_name_format(dns_zone_getorigin(zone),
08905 zonename, sizeof(zonename));
08906 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08907 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08908 "sync: dumping zone '%s/%s'%s%s%s: %s",
08909 zonename, classstr, sep, vname,
08910 cleanup ? ", removing journal file" : "",
08911 isc_result_totext(result));
08912 dns_zone_detach(&zone);
08913 return (result);
08914 }
08915
08916
08917
08918
08919 isc_result_t
08920 ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
08921 isc_buffer_t **text)
08922 {
08923 isc_result_t result, tresult;
08924 dns_zone_t *zone = NULL, *raw = NULL;
08925 dns_zonetype_t type;
08926 char classstr[DNS_RDATACLASS_FORMATSIZE];
08927 char zonename[DNS_NAME_FORMATSIZE];
08928 dns_view_t *view;
08929 const char *vname, *sep;
08930 isc_boolean_t frozen;
08931 const char *msg = NULL;
08932
08933 result = zone_from_args(server, args, NULL, &zone, NULL,
08934 text, ISC_TRUE);
08935 if (result != ISC_R_SUCCESS)
08936 return (result);
08937 if (zone == NULL) {
08938 result = isc_task_beginexclusive(server->task);
08939 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08940 tresult = ISC_R_SUCCESS;
08941 for (view = ISC_LIST_HEAD(server->viewlist);
08942 view != NULL;
08943 view = ISC_LIST_NEXT(view, link)) {
08944 result = dns_view_freezezones(view, freeze);
08945 if (result != ISC_R_SUCCESS &&
08946 tresult == ISC_R_SUCCESS)
08947 tresult = result;
08948 }
08949 isc_task_endexclusive(server->task);
08950 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
08951 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
08952 "%s all zones: %s",
08953 freeze ? "freezing" : "thawing",
08954 isc_result_totext(tresult));
08955 return (tresult);
08956 }
08957 dns_zone_getraw(zone, &raw);
08958 if (raw != NULL) {
08959 dns_zone_detach(&zone);
08960 dns_zone_attach(raw, &zone);
08961 dns_zone_detach(&raw);
08962 }
08963 type = dns_zone_gettype(zone);
08964 if (type != dns_zone_master) {
08965 dns_zone_detach(&zone);
08966 return (DNS_R_NOTMASTER);
08967 }
08968
08969 if (freeze && !dns_zone_isdynamic(zone, ISC_TRUE)) {
08970 dns_zone_detach(&zone);
08971 return (DNS_R_NOTDYNAMIC);
08972 }
08973
08974 result = isc_task_beginexclusive(server->task);
08975 RUNTIME_CHECK(result == ISC_R_SUCCESS);
08976 frozen = dns_zone_getupdatedisabled(zone);
08977 if (freeze) {
08978 if (frozen) {
08979 msg = "WARNING: The zone was already frozen.\n"
08980 "Someone else may be editing it or "
08981 "it may still be re-loading.";
08982 result = DNS_R_FROZEN;
08983 }
08984 if (result == ISC_R_SUCCESS) {
08985 result = dns_zone_flush(zone);
08986 if (result != ISC_R_SUCCESS)
08987 msg = "Flushing the zone updates to "
08988 "disk failed.";
08989 }
08990 if (result == ISC_R_SUCCESS)
08991 dns_zone_setupdatedisabled(zone, freeze);
08992 } else {
08993 if (frozen) {
08994 result = dns_zone_loadandthaw(zone);
08995 switch (result) {
08996 case ISC_R_SUCCESS:
08997 case DNS_R_UPTODATE:
08998 msg = "The zone reload and thaw was "
08999 "successful.";
09000 result = ISC_R_SUCCESS;
09001 break;
09002 case DNS_R_CONTINUE:
09003 msg = "A zone reload and thaw was started.\n"
09004 "Check the logs to see the result.";
09005 result = ISC_R_SUCCESS;
09006 break;
09007 }
09008 }
09009 }
09010 isc_task_endexclusive(server->task);
09011
09012 if (msg != NULL) {
09013 (void) putstr(text, msg);
09014 (void) putnull(text);
09015 }
09016
09017 view = dns_zone_getview(zone);
09018 if (strcmp(view->name, "_default") == 0 ||
09019 strcmp(view->name, "_bind") == 0)
09020 {
09021 vname = "";
09022 sep = "";
09023 } else {
09024 vname = view->name;
09025 sep = " ";
09026 }
09027 dns_rdataclass_format(dns_zone_getclass(zone), classstr,
09028 sizeof(classstr));
09029 dns_name_format(dns_zone_getorigin(zone),
09030 zonename, sizeof(zonename));
09031 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09032 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
09033 "%s zone '%s/%s'%s%s: %s",
09034 freeze ? "freezing" : "thawing",
09035 zonename, classstr, sep, vname,
09036 isc_result_totext(result));
09037 dns_zone_detach(&zone);
09038 return (result);
09039 }
09040
09041 #ifdef HAVE_LIBSCF
09042
09043
09044
09045
09046 isc_result_t
09047 ns_smf_add_message(isc_buffer_t **text) {
09048 return (putstr(text, "use svcadm(1M) to manage named"));
09049 }
09050 #endif
09051
09052
09053
09054
09055
09056 #define HEADER1 "# New zone file for view: "
09057 #define HEADER2 "\n# This file contains configuration for zones added by\n" \
09058 "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n"
09059 static isc_result_t
09060 add_comment(FILE *fp, const char *viewname) {
09061 isc_result_t result;
09062 CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL));
09063 CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL));
09064 CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL));
09065 cleanup:
09066 return (result);
09067 }
09068
09069 static isc_result_t
09070 nzf_remove(const char *nzfile, const char *viewname, const char *zonename) {
09071 isc_result_t result;
09072 FILE *ifp = NULL, *ofp = NULL;
09073 size_t znamelen = 0;
09074 char tmp[1024], buf[1024];
09075 isc_boolean_t inheader = ISC_TRUE;
09076
09077 znamelen = strlen(zonename);
09078
09079
09080 result = isc_stdio_open(nzfile, "r", &ifp);
09081 if (ifp != NULL && result == ISC_R_SUCCESS) {
09082 char *found = NULL, *p = NULL;
09083 size_t n;
09084
09085
09086 CHECK(isc_file_template("", "nzf-XXXXXXXX", tmp, sizeof(tmp)));
09087 CHECK(isc_file_openunique(tmp, &ofp));
09088 CHECK(add_comment(ofp, viewname));
09089
09090
09091 while (fgets(buf, 1024, ifp)) {
09092
09093 if (inheader && *buf == '#')
09094 continue;
09095 if (*buf != '#')
09096 inheader = ISC_FALSE;
09097
09098
09099
09100
09101
09102 if (strncasecmp(buf, "zone", 4) != 0) {
09103 fputs(buf, ofp);
09104 continue;
09105 }
09106 p = buf+4;
09107
09108
09109 while (*p &&
09110 ((*p == '"') || isspace((unsigned char)*p)))
09111 p++;
09112
09113
09114
09115
09116
09117 if (strncasecmp(p, zonename, znamelen) != 0) {
09118 fputs(buf, ofp);
09119 continue;
09120 }
09121
09122
09123
09124
09125
09126 p += znamelen;
09127 if (isspace((unsigned char)*p) ||
09128 *p == '"' || *p == '{') {
09129
09130 found = p;
09131 break;
09132 }
09133
09134
09135 fputs(buf, ofp);
09136 }
09137
09138
09139 if (found) {
09140 int openbrace = 0, closebrace = 0;
09141 for (;;) {
09142 while (*p) {
09143 if (*p == '{') openbrace++;
09144 if (*p == '}') closebrace++;
09145 p++;
09146 }
09147 if (openbrace && (openbrace == closebrace))
09148 break;
09149 if (!fgets(buf, 1024, ifp))
09150 break;
09151 p = buf;
09152 }
09153
09154
09155 result = isc_stdio_read(buf, 1, 1024, ifp, &n);
09156 while (n > 0U) {
09157 if (result == ISC_R_EOF)
09158 result = ISC_R_SUCCESS;
09159 CHECK(result);
09160 isc_stdio_write(buf, 1, n, ofp, NULL);
09161 result = isc_stdio_read(buf, 1, 1024, ifp, &n);
09162 }
09163
09164
09165
09166
09167
09168
09169 (void) isc_stdio_close(ifp);
09170 ifp = NULL;
09171 (void) isc_stdio_close(ofp);
09172 ofp = NULL;
09173
09174
09175 CHECK(isc_file_rename(tmp, nzfile));
09176 } else {
09177 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09178 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
09179 "deleted zone %s was missing from "
09180 "new zone file", zonename);
09181 goto cleanup;
09182 }
09183 }
09184
09185 cleanup:
09186 if (ifp != NULL)
09187 (void) isc_stdio_close(ifp);
09188 if (ofp != NULL)
09189 (void) isc_stdio_close(ofp);
09190
09191 return (result);
09192 }
09193
09194 static void
09195 dumpzone(void *arg, const char *buf, int len) {
09196 FILE *fp = arg;
09197
09198 isc_stdio_write(buf, len, 1, fp, NULL);
09199 }
09200
09201 static isc_result_t
09202 nzf_append(FILE *fp, const char *viewname, const cfg_obj_t *zconfig) {
09203 isc_result_t result;
09204 off_t offset;
09205
09206 CHECK(isc_stdio_seek(fp, 0, SEEK_END));
09207
09208 CHECK(isc_stdio_tell(fp, &offset));
09209 if (offset == 0)
09210 CHECK(add_comment(fp, viewname));
09211
09212 CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL));
09213 cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp);
09214 CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL));
09215
09216 cleanup:
09217 return (result);
09218 }
09219
09220 static isc_result_t
09221 newzone_parse(ns_server_t *server, char *args, dns_view_t **viewp,
09222 cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp)
09223 {
09224 isc_result_t result;
09225 isc_buffer_t argbuf;
09226 cfg_obj_t *zoneconf = NULL;
09227 const cfg_obj_t *zlist = NULL;
09228 const cfg_obj_t *zoneobj = NULL;
09229 const cfg_obj_t *obj = NULL;
09230 const char *viewname = NULL;
09231 dns_rdataclass_t rdclass;
09232 dns_view_t *view = NULL;
09233
09234 REQUIRE(viewp != NULL && *viewp == NULL);
09235
09236
09237 isc_buffer_init(&argbuf, args, (unsigned int) strlen(args));
09238 isc_buffer_add(&argbuf, strlen(args));
09239
09240
09241
09242
09243
09244 isc_buffer_forward(&argbuf, 3);
09245
09246 cfg_parser_reset(ns_g_addparser);
09247 CHECK(cfg_parse_buffer(ns_g_addparser, &argbuf,
09248 &cfg_type_addzoneconf, &zoneconf));
09249 CHECK(cfg_map_get(zoneconf, "zone", &zlist));
09250 if (! cfg_obj_islist(zlist))
09251 CHECK(ISC_R_FAILURE);
09252
09253
09254 zoneobj = cfg_listelt_value(cfg_list_first(zlist));
09255
09256
09257 obj = cfg_tuple_get(zoneobj, "class");
09258 CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass));
09259
09260
09261 obj = cfg_tuple_get(zoneobj, "view");
09262 if (obj && cfg_obj_isstring(obj))
09263 viewname = cfg_obj_asstring(obj);
09264 if (viewname == NULL || *viewname == '\0')
09265 viewname = "_default";
09266 CHECK(dns_viewlist_find(&server->viewlist, viewname, rdclass, &view));
09267
09268 *viewp = view;
09269 *zoneobjp = zoneobj;
09270 *zoneconfp = zoneconf;
09271
09272 return (ISC_R_SUCCESS);
09273
09274 cleanup:
09275 if (zoneconf != NULL)
09276 cfg_obj_destroy(ns_g_addparser, &zoneconf);
09277 if (view != NULL)
09278 dns_view_detach(&view);
09279
09280 return (result);
09281 }
09282
09283 static isc_result_t
09284 delete_zoneconf(cfg_parser_t *pctx, const cfg_obj_t *config,
09285 const char *zname)
09286 {
09287 const cfg_listelt_t *elt = NULL;
09288 const cfg_obj_t *zl = NULL;
09289 cfg_list_t *list;
09290
09291 REQUIRE(pctx != NULL);
09292 REQUIRE(config != NULL);
09293 REQUIRE(zname != NULL);
09294
09295 cfg_map_get(config, "zone", &zl);
09296
09297 if (! cfg_obj_islist(zl))
09298 return (ISC_R_FAILURE);
09299 DE_CONST(&zl->value.list, list);
09300
09301 for (elt = ISC_LIST_HEAD(*list);
09302 elt != NULL;
09303 elt = ISC_LIST_NEXT(elt, link))
09304 {
09305 const cfg_obj_t *zconf = cfg_listelt_value(elt);
09306 const char *zn;
09307 cfg_listelt_t *e;
09308
09309 zn = cfg_obj_asstring(cfg_tuple_get(zconf, "name"));
09310 if (strcasecmp(zname, zn) != 0)
09311 continue;
09312
09313 DE_CONST(elt, e);
09314 ISC_LIST_UNLINK(*list, e, link);
09315 cfg_obj_destroy(pctx, &e->obj);
09316 isc_mem_put(pctx->mctx, e, sizeof(*e));
09317 return (ISC_R_SUCCESS);
09318 }
09319
09320 return (ISC_R_NOTFOUND);
09321 }
09322
09323 static isc_result_t
09324 do_addzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
09325 dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj,
09326 isc_buffer_t **text)
09327 {
09328 isc_result_t result, tresult;
09329 dns_zone_t *zone = NULL;
09330 FILE *fp = NULL;
09331
09332
09333 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
09334 if (result == ISC_R_SUCCESS) {
09335 result = ISC_R_EXISTS;
09336 goto cleanup;
09337 } else if (result == DNS_R_PARTIALMATCH) {
09338
09339 dns_zone_detach(&zone);
09340 zone = NULL;
09341 } else if (result != ISC_R_NOTFOUND)
09342 goto cleanup;
09343
09344
09345 result = isc_stdio_open(view->new_zone_file, "a", &fp);
09346 if (result != ISC_R_SUCCESS) {
09347 TCHECK(putstr(text, "unable to open '"));
09348 TCHECK(putstr(text, view->new_zone_file));
09349 TCHECK(putstr(text, "': "));
09350 TCHECK(putstr(text, isc_result_totext(result)));
09351 goto cleanup;
09352 }
09353
09354
09355 result = isc_task_beginexclusive(server->task);
09356 RUNTIME_CHECK(result == ISC_R_SUCCESS);
09357 dns_view_thaw(view);
09358 result = configure_zone(cfg->config, zoneobj, cfg->vconfig,
09359 server->mctx, view, NULL, cfg->actx,
09360 ISC_TRUE, ISC_FALSE, ISC_FALSE);
09361 dns_view_freeze(view);
09362 isc_task_endexclusive(server->task);
09363 if (result != ISC_R_SUCCESS) {
09364 TCHECK(putstr(text, "configure_zone failed: "));
09365 TCHECK(putstr(text, isc_result_totext(result)));
09366 goto cleanup;
09367 }
09368
09369
09370 CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
09371
09372
09373
09374
09375
09376
09377 if (cfg->nzconfig == NULL)
09378 cfg_obj_attach(zoneconf, &cfg->nzconfig);
09379 else {
09380 cfg_obj_t *z;
09381 DE_CONST(zoneobj, z);
09382 CHECK(cfg_parser_mapadd(cfg->add_parser,
09383 cfg->nzconfig, z, "zone"));
09384 }
09385
09386
09387
09388
09389
09390 result = dns_zone_loadnew(zone);
09391 if (result != ISC_R_SUCCESS) {
09392 dns_db_t *dbp = NULL;
09393
09394 TCHECK(putstr(text, "dns_zone_loadnew failed: "));
09395 TCHECK(putstr(text, isc_result_totext(result)));
09396
09397 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09398 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
09399 "addzone failed; reverting.");
09400
09401
09402 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
09403 dns_db_detach(&dbp);
09404 dns_zone_unload(zone);
09405 }
09406
09407
09408 dns_zt_unmount(view->zonetable, zone);
09409 goto cleanup;
09410 }
09411
09412
09413 dns_zone_setadded(zone, ISC_TRUE);
09414
09415
09416 nzf_append(fp, view->name, zoneobj);
09417 result = ISC_R_SUCCESS;
09418
09419 cleanup:
09420 if (fp != NULL)
09421 (void) isc_stdio_close(fp);
09422 if (zone != NULL)
09423 dns_zone_detach(&zone);
09424
09425 return (result);
09426 }
09427
09428 static isc_result_t
09429 do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
09430 dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj,
09431 isc_buffer_t **text)
09432 {
09433 isc_result_t result, tresult;
09434 dns_zone_t *zone = NULL;
09435 isc_boolean_t added;
09436 FILE *fp = NULL;
09437 cfg_obj_t *z;
09438
09439
09440 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
09441 if (result != ISC_R_SUCCESS)
09442 goto cleanup;
09443
09444 added = dns_zone_getadded(zone);
09445 dns_zone_detach(&zone);
09446
09447
09448 result = isc_stdio_open(view->new_zone_file, "a", &fp);
09449 if (result != ISC_R_SUCCESS) {
09450 TCHECK(putstr(text, "unable to open '"));
09451 TCHECK(putstr(text, view->new_zone_file));
09452 TCHECK(putstr(text, "': "));
09453 TCHECK(putstr(text, isc_result_totext(result)));
09454 goto cleanup;
09455 }
09456 isc_stdio_close(fp);
09457 fp = NULL;
09458
09459 cfg = (ns_cfgctx_t *) view->new_zone_config;
09460 if (cfg == NULL) {
09461 TCHECK(putstr(text, "new zone config is not set"));
09462 CHECK(ISC_R_FAILURE);
09463 }
09464
09465
09466 result = isc_task_beginexclusive(server->task);
09467 RUNTIME_CHECK(result == ISC_R_SUCCESS);
09468 dns_view_thaw(view);
09469 result = configure_zone(cfg->config, zoneobj, cfg->vconfig,
09470 server->mctx, view, NULL, cfg->actx,
09471 ISC_TRUE, ISC_FALSE, ISC_TRUE);
09472 dns_view_freeze(view);
09473 isc_task_endexclusive(server->task);
09474 if (result != ISC_R_SUCCESS) {
09475 TCHECK(putstr(text, "configure_zone failed: "));
09476 TCHECK(putstr(text, isc_result_totext(result)));
09477 goto cleanup;
09478 }
09479
09480
09481 CHECK(dns_zt_find(view->zonetable, name, 0, NULL, &zone));
09482
09483
09484 if (added) {
09485 delete_zoneconf(cfg->add_parser, cfg->nzconfig, zname);
09486 nzf_remove(view->new_zone_file, view->name, zname);
09487 } else {
09488 if (cfg->vconfig == NULL)
09489 delete_zoneconf(cfg->conf_parser, cfg->config, zname);
09490 else {
09491 const cfg_obj_t *voptions =
09492 cfg_tuple_get(cfg->vconfig, "options");
09493 delete_zoneconf(cfg->conf_parser, voptions, zname);
09494 }
09495 }
09496
09497
09498 result = dns_zone_loadnew(zone);
09499 if (result != ISC_R_SUCCESS) {
09500 dns_db_t *dbp = NULL;
09501
09502 TCHECK(putstr(text, "failed to load zone '"));
09503 TCHECK(putstr(text, zname));
09504 TCHECK(putstr(text, "': "));
09505 TCHECK(putstr(text, isc_result_totext(result)));
09506 TCHECK(putstr(text, "\nThe zone is no longer being served. "));
09507 TCHECK(putstr(text, "Use 'rndc addzone' to correct\n"));
09508 TCHECK(putstr(text, "the problem and restore service."));
09509
09510 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09511 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
09512 "modzone failed; removing zone.");
09513
09514
09515 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
09516 dns_db_detach(&dbp);
09517 dns_zone_unload(zone);
09518 }
09519
09520
09521 dns_zt_unmount(view->zonetable, zone);
09522 goto cleanup;
09523 }
09524
09525
09526 DE_CONST(zoneobj, z);
09527 CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzconfig, z, "zone"));
09528
09529 if (added) {
09530 CHECK(isc_stdio_open(view->new_zone_file, "a", &fp));
09531 nzf_append(fp, view->name, zoneobj);
09532 (void) isc_stdio_close(fp);
09533 fp = NULL;
09534
09535 TCHECK(putstr(text, "zone '"));
09536 TCHECK(putstr(text, zname));
09537 TCHECK(putstr(text, "' reconfigured."));
09538 } else {
09539 TCHECK(putstr(text, "zone '"));
09540 TCHECK(putstr(text, zname));
09541 TCHECK(putstr(text, "' must also be reconfigured in\n"));
09542 TCHECK(putstr(text, "named.conf to make changes permanent."));
09543 }
09544
09545 cleanup:
09546 if (fp != NULL)
09547 isc_stdio_close(fp);
09548 if (zone != NULL)
09549 dns_zone_detach(&zone);
09550
09551 return (result);
09552 }
09553
09554
09555
09556
09557 isc_result_t
09558 ns_server_changezone(ns_server_t *server, char *args, isc_buffer_t **text) {
09559 isc_result_t result;
09560 isc_boolean_t addzone;
09561 ns_cfgctx_t *cfg = NULL;
09562 cfg_obj_t *zoneconf = NULL;
09563 const cfg_obj_t *zoneobj = NULL;
09564 const char *zonename;
09565 dns_view_t *view = NULL;
09566 isc_buffer_t buf;
09567 dns_fixedname_t fname;
09568 dns_name_t *dnsname;
09569
09570 if (strncasecmp(args, "add", 3) == 0)
09571 addzone = ISC_TRUE;
09572 else
09573 addzone = ISC_FALSE;
09574
09575 CHECK(newzone_parse(server, args, &view, &zoneconf, &zoneobj));
09576
09577
09578 if (view->new_zone_file == NULL) {
09579 result = ISC_R_NOPERM;
09580 goto cleanup;
09581 }
09582
09583 cfg = (ns_cfgctx_t *) view->new_zone_config;
09584 if (cfg == NULL) {
09585 result = ISC_R_FAILURE;
09586 goto cleanup;
09587 }
09588
09589 zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name"));
09590 isc_buffer_constinit(&buf, zonename, strlen(zonename));
09591 isc_buffer_add(&buf, strlen(zonename));
09592
09593 dns_fixedname_init(&fname);
09594 dnsname = dns_fixedname_name(&fname);
09595 CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, ISC_FALSE, NULL));
09596
09597 if (addzone)
09598 CHECK(do_addzone(server, cfg, view, dnsname, zoneconf,
09599 zoneobj, text));
09600 else
09601 CHECK(do_modzone(server, cfg, view, dnsname, zonename,
09602 zoneobj, text));
09603
09604 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09605 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
09606 "%s zone %s in view %s via %s",
09607 addzone ? "added" : "updated",
09608 zonename, view->name,
09609 addzone ? NS_COMMAND_ADDZONE : NS_COMMAND_MODZONE);
09610
09611
09612 CHECK(isc_time_now(&ns_g_configtime));
09613
09614 cleanup:
09615 if (isc_buffer_usedlength(*text) > 0)
09616 (void) putnull(text);
09617 if (zoneconf != NULL)
09618 cfg_obj_destroy(ns_g_addparser, &zoneconf);
09619 if (view != NULL)
09620 dns_view_detach(&view);
09621
09622 return (result);
09623 }
09624
09625 static isc_boolean_t
09626 inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) {
09627 if (file != NULL && isc_file_exists(file)) {
09628 if (first)
09629 (void) putstr(text,
09630 "The following files were in use "
09631 "and may now be removed:\n");
09632 else
09633 (void) putstr(text, "\n");
09634 (void) putstr(text, file);
09635 (void) putnull(text);
09636 return (ISC_FALSE);
09637 }
09638 return (first);
09639 }
09640
09641
09642
09643
09644 isc_result_t
09645 ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text) {
09646 isc_result_t result, tresult;
09647 ns_cfgctx_t *cfg = NULL;
09648 dns_zone_t *zone = NULL;
09649 dns_zone_t *raw = NULL;
09650 dns_zone_t *mayberaw;
09651 dns_view_t *view = NULL;
09652 dns_db_t *dbp = NULL;
09653 const char *zonename = NULL;
09654 isc_boolean_t exclusive = ISC_FALSE;
09655 isc_boolean_t cleanup = ISC_FALSE;
09656 const char *file, *arg;
09657 isc_boolean_t added;
09658
09659
09660 arg = next_token(&args, " \t");
09661 if (arg == NULL)
09662 return (ISC_R_UNEXPECTEDEND);
09663
09664
09665 arg = next_token(&args, " \t");
09666 if (arg == NULL)
09667 return (ISC_R_UNEXPECTEDEND);
09668
09669 if (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0) {
09670 cleanup = ISC_TRUE;
09671 arg = next_token(&args, " \t");
09672 }
09673
09674 CHECK(zone_from_args(server, args, arg, &zone, &zonename,
09675 text, ISC_FALSE));
09676 if (zone == NULL) {
09677 result = ISC_R_UNEXPECTEDEND;
09678 goto cleanup;
09679 }
09680
09681 INSIST(zonename != NULL);
09682
09683 result = isc_task_beginexclusive(server->task);
09684 RUNTIME_CHECK(result == ISC_R_SUCCESS);
09685 exclusive = ISC_TRUE;
09686
09687
09688 view = dns_zone_getview(zone);
09689 cfg = (ns_cfgctx_t *) view->new_zone_config;
09690
09691
09692 added = dns_zone_getadded(zone);
09693 if (added) {
09694 if (view->new_zone_file != NULL)
09695 nzf_remove(view->new_zone_file, view->name, zonename);
09696 if (cfg != NULL)
09697 delete_zoneconf(cfg->add_parser, cfg->nzconfig,
09698 zonename);
09699 } else if (cfg != NULL) {
09700 if (cfg->vconfig != NULL) {
09701 const cfg_obj_t *voptions =
09702 cfg_tuple_get(cfg->vconfig, "options");
09703 delete_zoneconf(cfg->conf_parser, voptions,
09704 zonename);
09705 } else {
09706 delete_zoneconf(cfg->conf_parser, cfg->config,
09707 zonename);
09708 }
09709 }
09710
09711
09712 if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
09713 dns_db_detach(&dbp);
09714 dns_zone_unload(zone);
09715 }
09716
09717
09718 added = dns_zone_getadded(zone);
09719 if (added && view->new_zone_file != NULL)
09720 CHECK(nzf_remove(view->new_zone_file, view->name, zonename));
09721
09722
09723 dns_zone_getraw(zone, &raw);
09724 mayberaw = (raw != NULL) ? raw : zone;
09725
09726 if (!added) {
09727 TCHECK(putstr(text, "zone '"));
09728 TCHECK(putstr(text, zonename));
09729 TCHECK(putstr(text, "' is no longer loaded.\n"));
09730 TCHECK(putstr(text, "To keep it from returning "));
09731 TCHECK(putstr(text, "when the server is restarted, it\n"));
09732 TCHECK(putstr(text, "must also be removed from named.conf."));
09733 } else if (cleanup) {
09734 file = dns_zone_getfile(mayberaw);
09735 isc_file_remove(file);
09736
09737 file = dns_zone_getjournal(mayberaw);
09738 isc_file_remove(file);
09739
09740 if (zone != mayberaw) {
09741 file = dns_zone_getfile(zone);
09742 isc_file_remove(file);
09743
09744 file = dns_zone_getjournal(zone);
09745 isc_file_remove(file);
09746 }
09747 TCHECK(putstr(text, "zone '"));
09748 TCHECK(putstr(text, zonename));
09749 TCHECK(putstr(text, "' and associated files were deleted."));
09750 } else if (dns_zone_gettype(mayberaw) == dns_zone_slave ||
09751 dns_zone_gettype(mayberaw) == dns_zone_stub)
09752 {
09753 isc_boolean_t first;
09754
09755 TCHECK(putstr(text, "zone '"));
09756 TCHECK(putstr(text, zonename));
09757 TCHECK(putstr(text, "' was deleted.\n"));
09758
09759 file = dns_zone_getfile(mayberaw);
09760 first = inuse(file, ISC_TRUE, text);
09761
09762 file = dns_zone_getjournal(mayberaw);
09763 first = inuse(file, first, text);
09764
09765 if (zone != mayberaw) {
09766 file = dns_zone_getfile(zone);
09767 first = inuse(file, first, text);
09768
09769 file = dns_zone_getjournal(zone);
09770 (void) inuse(file, first, text);
09771 }
09772 }
09773
09774 CHECK(dns_zt_unmount(view->zonetable, zone));
09775
09776 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09777 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
09778 "zone %s removed via delzone", zonename);
09779
09780
09781 CHECK(isc_time_now(&ns_g_configtime));
09782
09783 result = ISC_R_SUCCESS;
09784
09785 cleanup:
09786 if (isc_buffer_usedlength(*text) > 0)
09787 (void) putnull(text);
09788 if (raw != NULL)
09789 dns_zone_detach(&raw);
09790 if (exclusive)
09791 isc_task_endexclusive(server->task);
09792 if (zone != NULL)
09793 dns_zone_detach(&zone);
09794
09795 return (result);
09796 }
09797
09798
09799
09800
09801 static const cfg_obj_t *
09802 find_name_in_list_from_map(const cfg_obj_t *config,
09803 const char *map_key_for_list,
09804 const char *name)
09805 {
09806 const cfg_obj_t *list = NULL;
09807 const cfg_listelt_t *element;
09808 const cfg_obj_t *result = NULL;
09809
09810 cfg_map_get(config, map_key_for_list, &list);
09811 for (element = cfg_list_first(list);
09812 element != NULL;
09813 element = cfg_list_next(element))
09814 {
09815 const char *vname;
09816 result = cfg_listelt_value(element);
09817 INSIST(result != NULL);
09818 vname = cfg_obj_asstring(cfg_tuple_get(result, "name"));
09819 if (vname != NULL && !strcasecmp(vname, name))
09820 break;
09821 result = NULL;
09822 }
09823
09824 return (result);
09825 }
09826
09827 static void
09828 emitzone(void *arg, const char *buf, int len) {
09829 isc_buffer_t **tpp = arg;
09830 putmem(tpp, buf, len);
09831 }
09832
09833 isc_result_t
09834 ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text) {
09835 isc_result_t result;
09836 const cfg_obj_t *vconfig = NULL, *zconfig = NULL;
09837 const char *zonename = NULL;
09838 const cfg_obj_t *map;
09839 dns_view_t *view = NULL;
09840 dns_zone_t *zone = NULL;
09841 ns_cfgctx_t *cfg = NULL;
09842 isc_boolean_t exclusive = ISC_FALSE;
09843
09844
09845 CHECK(zone_from_args(server, args, NULL, &zone, &zonename,
09846 text, ISC_TRUE));
09847 if (zone == NULL) {
09848 result = ISC_R_UNEXPECTEDEND;
09849 goto cleanup;
09850 }
09851
09852 view = dns_zone_getview(zone);
09853 dns_zone_detach(&zone);
09854
09855 cfg = (ns_cfgctx_t *) view->new_zone_config;
09856 if (cfg == NULL) {
09857 result = ISC_R_FAILURE;
09858 goto cleanup;
09859 }
09860
09861 result = isc_task_beginexclusive(server->task);
09862 RUNTIME_CHECK(result == ISC_R_SUCCESS);
09863 exclusive = ISC_TRUE;
09864
09865
09866 vconfig = find_name_in_list_from_map(cfg->config, "view", view->name);
09867
09868
09869 if (vconfig != NULL)
09870 map = cfg_tuple_get(vconfig, "options");
09871 else
09872 map = cfg->config;
09873
09874 zconfig = find_name_in_list_from_map(map, "zone", zonename);
09875 if (zconfig == NULL)
09876 zconfig = find_name_in_list_from_map(cfg->nzconfig,
09877 "zone", zonename);
09878 if (zconfig == NULL)
09879 CHECK(ISC_R_NOTFOUND);
09880
09881 putstr(text, "zone ");
09882 cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, text);
09883 putstr(text, ";");
09884
09885 result = ISC_R_SUCCESS;
09886
09887 cleanup:
09888 if (isc_buffer_usedlength(*text) > 0)
09889 (void) putnull(text);
09890 if (exclusive)
09891 isc_task_endexclusive(server->task);
09892
09893 return (result);
09894 }
09895
09896 static void
09897 newzone_cfgctx_destroy(void **cfgp) {
09898 ns_cfgctx_t *cfg;
09899
09900 REQUIRE(cfgp != NULL && *cfgp != NULL);
09901
09902 cfg = *cfgp;
09903
09904 if (cfg->conf_parser != NULL) {
09905 if (cfg->config != NULL)
09906 cfg_obj_destroy(cfg->conf_parser, &cfg->config);
09907 if (cfg->vconfig != NULL)
09908 cfg_obj_destroy(cfg->conf_parser, &cfg->vconfig);
09909 cfg_parser_destroy(&cfg->conf_parser);
09910 }
09911 if (cfg->add_parser != NULL) {
09912 if (cfg->nzconfig != NULL)
09913 cfg_obj_destroy(cfg->add_parser, &cfg->nzconfig);
09914 cfg_parser_destroy(&cfg->add_parser);
09915 }
09916
09917 if (cfg->actx != NULL)
09918 cfg_aclconfctx_detach(&cfg->actx);
09919
09920 isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg));
09921 *cfgp = NULL;
09922 }
09923
09924 static isc_result_t
09925 generate_salt(unsigned char *salt, size_t saltlen) {
09926 int i, n;
09927 union {
09928 unsigned char rnd[256];
09929 isc_uint32_t rnd32[64];
09930 } rnd;
09931 unsigned char text[512 + 1];
09932 isc_region_t r;
09933 isc_buffer_t buf;
09934 isc_result_t result;
09935
09936 if (saltlen > 256U)
09937 return (ISC_R_RANGE);
09938
09939 n = (int) (saltlen + sizeof(isc_uint32_t) - 1) / sizeof(isc_uint32_t);
09940 for (i = 0; i < n; i++)
09941 isc_random_get(&rnd.rnd32[i]);
09942
09943 memmove(salt, rnd.rnd, saltlen);
09944
09945 r.base = rnd.rnd;
09946 r.length = (unsigned int) saltlen;
09947
09948 isc_buffer_init(&buf, text, sizeof(text));
09949 result = isc_hex_totext(&r, 2, "", &buf);
09950 RUNTIME_CHECK(result == ISC_R_SUCCESS);
09951 text[saltlen * 2] = 0;
09952
09953 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
09954 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
09955 "generated salt: %s", text);
09956
09957 return (ISC_R_SUCCESS);
09958 }
09959
09960 isc_result_t
09961 ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) {
09962 isc_result_t result = ISC_R_SUCCESS;
09963 dns_zone_t *zone = NULL;
09964 dns_name_t *origin;
09965 dns_db_t *db = NULL;
09966 dns_dbnode_t *node = NULL;
09967 dns_dbversion_t *version = NULL;
09968 dns_rdatatype_t privatetype;
09969 dns_rdataset_t privset;
09970 isc_boolean_t first = ISC_TRUE;
09971 isc_boolean_t list = ISC_FALSE, clear = ISC_FALSE;
09972 isc_boolean_t chain = ISC_FALSE;
09973 isc_boolean_t setserial = ISC_FALSE;
09974 isc_uint32_t serial = 0;
09975 char keystr[DNS_SECALG_FORMATSIZE + 7];
09976 unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0;
09977 unsigned char salt[255];
09978 const char *ptr;
09979 size_t n;
09980
09981 dns_rdataset_init(&privset);
09982
09983
09984 ptr = next_token(&args, " \t");
09985 if (ptr == NULL)
09986 return (ISC_R_UNEXPECTEDEND);
09987
09988
09989 ptr = next_token(&args, " \t");
09990 if (ptr == NULL)
09991 return (ISC_R_UNEXPECTEDEND);
09992
09993 if (strcasecmp(ptr, "-list") == 0)
09994 list = ISC_TRUE;
09995 else if ((strcasecmp(ptr, "-clear") == 0) ||
09996 (strcasecmp(ptr, "-clean") == 0)) {
09997 clear = ISC_TRUE;
09998 ptr = next_token(&args, " \t");
09999 if (ptr == NULL)
10000 return (ISC_R_UNEXPECTEDEND);
10001 strlcpy(keystr, ptr, sizeof(keystr));
10002 } else if (strcasecmp(ptr, "-nsec3param") == 0) {
10003 const char *hashstr, *flagstr, *iterstr;
10004 char nbuf[512];
10005
10006 chain = ISC_TRUE;
10007 hashstr = next_token(&args, " \t");
10008 if (hashstr == NULL)
10009 return (ISC_R_UNEXPECTEDEND);
10010
10011 if (strcasecmp(hashstr, "none") == 0)
10012 hash = 0;
10013 else {
10014 flagstr = next_token(&args, " \t");
10015 iterstr = next_token(&args, " \t");
10016 if (flagstr == NULL || iterstr == NULL)
10017 return (ISC_R_UNEXPECTEDEND);
10018
10019 n = snprintf(nbuf, sizeof(nbuf), "%s %s %s",
10020 hashstr, flagstr, iterstr);
10021 if (n == sizeof(nbuf))
10022 return (ISC_R_NOSPACE);
10023 n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter);
10024 if (n != 3U)
10025 return (ISC_R_BADNUMBER);
10026
10027 if (hash > 0xffU || flags > 0xffU)
10028 return (ISC_R_RANGE);
10029
10030 ptr = next_token(&args, " \t");
10031 if (ptr == NULL) {
10032 return (ISC_R_UNEXPECTEDEND);
10033 } else if (strcasecmp(ptr, "auto") == 0) {
10034
10035
10036
10037
10038
10039
10040 saltlen = 8;
10041 CHECK(generate_salt(salt, saltlen));
10042 } else if (strcmp(ptr, "-") != 0) {
10043 isc_buffer_t buf;
10044
10045 isc_buffer_init(&buf, salt, sizeof(salt));
10046 CHECK(isc_hex_decodestring(ptr, &buf));
10047 saltlen = isc_buffer_usedlength(&buf);
10048 }
10049 }
10050 } else if (strcasecmp(ptr, "-serial") == 0) {
10051 ptr = next_token(&args, " \t");
10052 if (ptr == NULL)
10053 return (ISC_R_UNEXPECTEDEND);
10054 CHECK(isc_parse_uint32(&serial, ptr, 10));
10055 setserial = ISC_TRUE;
10056 } else
10057 CHECK(DNS_R_SYNTAX);
10058
10059 CHECK(zone_from_args(server, args, NULL, &zone, NULL,
10060 text, ISC_FALSE));
10061 if (zone == NULL)
10062 CHECK(ISC_R_UNEXPECTEDEND);
10063
10064 if (clear) {
10065 CHECK(dns_zone_keydone(zone, keystr));
10066 (void) putstr(text, "request queued");
10067 (void) putnull(text);
10068 } else if (chain) {
10069 CHECK(dns_zone_setnsec3param(zone, (isc_uint8_t)hash,
10070 (isc_uint8_t)flags, iter,
10071 (isc_uint8_t)saltlen, salt,
10072 ISC_TRUE));
10073 (void) putstr(text, "nsec3param request queued");
10074 (void) putnull(text);
10075 } else if (setserial) {
10076 CHECK(dns_zone_setserial(zone, serial));
10077 (void) putstr(text, "serial request queued");
10078 (void) putnull(text);
10079 } else if (list) {
10080 privatetype = dns_zone_getprivatetype(zone);
10081 origin = dns_zone_getorigin(zone);
10082 CHECK(dns_zone_getdb(zone, &db));
10083 CHECK(dns_db_findnode(db, origin, ISC_FALSE, &node));
10084 dns_db_currentversion(db, &version);
10085
10086 result = dns_db_findrdataset(db, node, version, privatetype,
10087 dns_rdatatype_none, 0,
10088 &privset, NULL);
10089 if (result == ISC_R_NOTFOUND) {
10090 (void) putstr(text, "No signing records found");
10091 (void) putnull(text);
10092 result = ISC_R_SUCCESS;
10093 goto cleanup;
10094 }
10095
10096 for (result = dns_rdataset_first(&privset);
10097 result == ISC_R_SUCCESS;
10098 result = dns_rdataset_next(&privset))
10099 {
10100 dns_rdata_t priv = DNS_RDATA_INIT;
10101 char output[BUFSIZ];
10102 isc_buffer_t buf;
10103
10104 dns_rdataset_current(&privset, &priv);
10105
10106 isc_buffer_init(&buf, output, sizeof(output));
10107 CHECK(dns_private_totext(&priv, &buf));
10108 if (!first)
10109 CHECK(putstr(text, "\n"));
10110 CHECK(putstr(text, output));
10111 first = ISC_FALSE;
10112 }
10113 if (!first)
10114 CHECK(putnull(text));
10115
10116 if (result == ISC_R_NOMORE)
10117 result = ISC_R_SUCCESS;
10118 }
10119
10120 cleanup:
10121 if (dns_rdataset_isassociated(&privset))
10122 dns_rdataset_disassociate(&privset);
10123 if (node != NULL)
10124 dns_db_detachnode(db, &node);
10125 if (version != NULL)
10126 dns_db_closeversion(db, &version, ISC_FALSE);
10127 if (db != NULL)
10128 dns_db_detach(&db);
10129 if (zone != NULL)
10130 dns_zone_detach(&zone);
10131
10132 return (result);
10133 }
10134
10135 static isc_result_t
10136 putmem(isc_buffer_t **b, const char *str, size_t len) {
10137 isc_result_t result;
10138
10139 result = isc_buffer_reserve(b, (unsigned int)len);
10140 if (result != ISC_R_SUCCESS)
10141 return (ISC_R_NOSPACE);
10142
10143 isc_buffer_putmem(*b, (const unsigned char *)str, (unsigned int)len);
10144 return (ISC_R_SUCCESS);
10145 }
10146
10147 static inline isc_result_t
10148 putstr(isc_buffer_t **b, const char *str) {
10149 return (putmem(b, str, strlen(str)));
10150 }
10151
10152 static isc_result_t
10153 putuint8(isc_buffer_t **b, isc_uint8_t val) {
10154 isc_result_t result;
10155
10156 result = isc_buffer_reserve(b, 1);
10157 if (result != ISC_R_SUCCESS)
10158 return (ISC_R_NOSPACE);
10159
10160 isc_buffer_putuint8(*b, val);
10161 return (ISC_R_SUCCESS);
10162 }
10163
10164 static inline isc_result_t
10165 putnull(isc_buffer_t **b) {
10166 return (putuint8(b, 0));
10167 }
10168
10169 isc_result_t
10170 ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text) {
10171 isc_result_t result = ISC_R_SUCCESS;
10172 dns_zone_t *zone = NULL, *raw = NULL;
10173 const char *type, *file, *zonename = NULL;
10174 isc_uint32_t serial, signed_serial, nodes;
10175 char serbuf[16], sserbuf[16], nodebuf[16], resignbuf[512];
10176 char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
10177 char xbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
10178 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
10179 char kbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
10180 char rtbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
10181 isc_time_t loadtime, expiretime, refreshtime;
10182 isc_time_t refreshkeytime, resigntime;
10183 dns_zonetype_t zonetype;
10184 isc_boolean_t dynamic = ISC_FALSE, frozen = ISC_FALSE;
10185 isc_boolean_t hasraw = ISC_FALSE;
10186 isc_boolean_t secure, maintain, allow;
10187 dns_db_t *db = NULL, *rawdb = NULL;
10188 char **incfiles = NULL;
10189 int nfiles = 0;
10190
10191 isc_time_settoepoch(&loadtime);
10192 isc_time_settoepoch(&refreshtime);
10193 isc_time_settoepoch(&expiretime);
10194 isc_time_settoepoch(&refreshkeytime);
10195 isc_time_settoepoch(&resigntime);
10196
10197 CHECK(zone_from_args(server, args, NULL, &zone, &zonename,
10198 text, ISC_TRUE));
10199 if (zone == NULL) {
10200 result = ISC_R_UNEXPECTEDEND;
10201 goto cleanup;
10202 }
10203
10204 zonetype = dns_zone_gettype(zone);
10205 switch (zonetype) {
10206 case dns_zone_master:
10207 type = "master";
10208 break;
10209 case dns_zone_slave:
10210 type = "slave";
10211 break;
10212 case dns_zone_stub:
10213 type = "stub";
10214 break;
10215 case dns_zone_staticstub:
10216 type = "staticstub";
10217 break;
10218 case dns_zone_redirect:
10219 type = "redirect";
10220 break;
10221 case dns_zone_key:
10222 type = "key";
10223 break;
10224 case dns_zone_dlz:
10225 type = "dlz";
10226 break;
10227 default:
10228 type = "unknown";
10229 }
10230
10231
10232 CHECK(dns_zone_getdb(zone, &db));
10233 dns_zone_getraw(zone, &raw);
10234 hasraw = ISC_TF(raw != NULL);
10235 if (hasraw)
10236 CHECK(dns_zone_getdb(raw, &rawdb));
10237
10238
10239 serial = dns_zone_getserial(hasraw ? raw : zone);
10240 snprintf(serbuf, sizeof(serbuf), "%d", serial);
10241 if (hasraw) {
10242 signed_serial = dns_zone_getserial(zone);
10243 snprintf(sserbuf, sizeof(sserbuf), "%d", signed_serial);
10244 }
10245
10246
10247 nodes = dns_db_nodecount(hasraw ? rawdb : db);
10248 snprintf(nodebuf, sizeof(nodebuf), "%d", nodes);
10249
10250
10251 secure = dns_db_issecure(db);
10252 allow = ISC_TF((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_ALLOW) != 0);
10253 maintain = ISC_TF((dns_zone_getkeyopts(zone) &
10254 DNS_ZONEKEY_MAINTAIN) != 0);
10255
10256
10257 file = dns_zone_getfile(hasraw ? raw : zone);
10258 nfiles = dns_zone_getincludes(hasraw ? raw : zone, &incfiles);
10259
10260
10261 dns_zone_getloadtime(zone, &loadtime);
10262 isc_time_formathttptimestamp(&loadtime, lbuf, sizeof(lbuf));
10263
10264
10265 if (zonetype == dns_zone_slave ||
10266 zonetype == dns_zone_stub ||
10267 zonetype == dns_zone_redirect)
10268 {
10269 dns_zone_getexpiretime(zone, &expiretime);
10270 isc_time_formathttptimestamp(&expiretime, xbuf, sizeof(xbuf));
10271 dns_zone_getrefreshtime(zone, &refreshtime);
10272 isc_time_formathttptimestamp(&refreshtime, rbuf, sizeof(rbuf));
10273 }
10274
10275
10276 if (zonetype == dns_zone_master ||
10277 (zonetype == dns_zone_slave && hasraw))
10278 {
10279 dns_zone_getrefreshkeytime(zone, &refreshkeytime);
10280 isc_time_formathttptimestamp(&refreshkeytime, kbuf,
10281 sizeof(kbuf));
10282 }
10283
10284
10285 if (zonetype == dns_zone_master) {
10286 dynamic = dns_zone_isdynamic(hasraw ? raw : zone, ISC_TRUE);
10287 frozen = dynamic && !dns_zone_isdynamic(hasraw ? raw : zone,
10288 ISC_FALSE);
10289 }
10290
10291
10292 if (secure && (zonetype == dns_zone_master ||
10293 (zonetype == dns_zone_slave && hasraw)) &&
10294 ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_NORESIGN) == 0))
10295 {
10296 dns_name_t *name;
10297 dns_fixedname_t fixed;
10298 dns_rdataset_t next;
10299
10300 dns_rdataset_init(&next);
10301 dns_fixedname_init(&fixed);
10302 name = dns_fixedname_name(&fixed);
10303
10304 result = dns_db_getsigningtime(db, &next, name);
10305 if (result == ISC_R_SUCCESS) {
10306 isc_stdtime_t timenow;
10307 char namebuf[DNS_NAME_FORMATSIZE];
10308 char typebuf[DNS_RDATATYPE_FORMATSIZE];
10309
10310 isc_stdtime_get(&timenow);
10311 dns_name_format(name, namebuf, sizeof(namebuf));
10312 dns_rdatatype_format(next.covers,
10313 typebuf, sizeof(typebuf));
10314 snprintf(resignbuf, sizeof(resignbuf),
10315 "%s/%s", namebuf, typebuf);
10316 isc_time_set(&resigntime, next.resign -
10317 dns_zone_getsigresigninginterval(zone), 0);
10318 isc_time_formathttptimestamp(&resigntime, rtbuf,
10319 sizeof(rtbuf));
10320 dns_rdataset_disassociate(&next);
10321 }
10322 }
10323
10324
10325 CHECK(putstr(text, "name: "));
10326 CHECK(putstr(text, zonename));
10327
10328 CHECK(putstr(text, "\ntype: "));
10329 CHECK(putstr(text, type));
10330
10331 if (file != NULL) {
10332 int i;
10333 CHECK(putstr(text, "\nfiles: "));
10334 CHECK(putstr(text, file));
10335 for (i = 0; i < nfiles; i++) {
10336 CHECK(putstr(text, ", "));
10337 if (incfiles[i] != NULL)
10338 CHECK(putstr(text, incfiles[i]));
10339 }
10340 }
10341
10342 CHECK(putstr(text, "\nserial: "));
10343 CHECK(putstr(text, serbuf));
10344 if (hasraw) {
10345 CHECK(putstr(text, "\nsigned serial: "));
10346 CHECK(putstr(text, sserbuf));
10347 }
10348
10349 CHECK(putstr(text, "\nnodes: "));
10350 CHECK(putstr(text, nodebuf));
10351
10352 if (! isc_time_isepoch(&loadtime)) {
10353 CHECK(putstr(text, "\nlast loaded: "));
10354 CHECK(putstr(text, lbuf));
10355 }
10356
10357 if (! isc_time_isepoch(&refreshtime)) {
10358 CHECK(putstr(text, "\nnext refresh: "));
10359 CHECK(putstr(text, rbuf));
10360 }
10361
10362 if (! isc_time_isepoch(&expiretime)) {
10363 CHECK(putstr(text, "\nexpires: "));
10364 CHECK(putstr(text, xbuf));
10365 }
10366
10367 if (secure) {
10368 CHECK(putstr(text, "\nsecure: yes"));
10369 if (hasraw)
10370 CHECK(putstr(text, "\ninline signing: yes"));
10371 else
10372 CHECK(putstr(text, "\ninline signing: no"));
10373 } else
10374 CHECK(putstr(text, "\nsecure: no"));
10375
10376 if (maintain) {
10377 CHECK(putstr(text, "\nkey maintenance: automatic"));
10378 if (! isc_time_isepoch(&refreshkeytime)) {
10379 CHECK(putstr(text, "\nnext key event: "));
10380 CHECK(putstr(text, kbuf));
10381 }
10382 } else if (allow)
10383 CHECK(putstr(text, "\nkey maintenance: on command"));
10384 else if (secure || hasraw)
10385 CHECK(putstr(text, "\nkey maintenance: none"));
10386
10387 if (!isc_time_isepoch(&resigntime)) {
10388 CHECK(putstr(text, "\nnext resign node: "));
10389 CHECK(putstr(text, resignbuf));
10390 CHECK(putstr(text, "\nnext resign time: "));
10391 CHECK(putstr(text, rtbuf));
10392 }
10393
10394 if (dynamic) {
10395 CHECK(putstr(text, "\ndynamic: yes"));
10396 if (frozen)
10397 CHECK(putstr(text, "\nfrozen: yes"));
10398 else
10399 CHECK(putstr(text, "\nfrozen: no"));
10400 } else
10401 CHECK(putstr(text, "\ndynamic: no"));
10402
10403 CHECK(putstr(text, "\nreconfigurable via modzone: "));
10404 CHECK(putstr(text, dns_zone_getadded(zone) ? "yes" : "no"));
10405
10406 cleanup:
10407
10408 if (result == ISC_R_NOSPACE)
10409 (void) putstr(text, "\n...");
10410 if ((result == ISC_R_SUCCESS || result == ISC_R_NOSPACE))
10411 (void) putnull(text);
10412
10413 if (db != NULL)
10414 dns_db_detach(&db);
10415 if (rawdb != NULL)
10416 dns_db_detach(&rawdb);
10417 if (incfiles != NULL) {
10418 int i;
10419 isc_mem_t *mctx = dns_zone_getmctx(hasraw ? raw : zone);
10420
10421 for (i = 0; i < nfiles; i++)
10422 if (incfiles[i] != NULL)
10423 isc_mem_free(mctx, incfiles[i]);
10424 isc_mem_free(mctx, incfiles);
10425 }
10426 if (raw != NULL)
10427 dns_zone_detach(&raw);
10428 if (zone != NULL)
10429 dns_zone_detach(&zone);
10430 return (result);
10431 }
10432
10433 static inline isc_boolean_t
10434 argcheck(char *cmd, const char *full) {
10435 size_t l;
10436
10437 if (cmd == NULL || cmd[0] != '-')
10438 return (ISC_FALSE);
10439
10440 cmd++;
10441 l = strlen(cmd);
10442 if (l > strlen(full) || strncasecmp(cmd, full, l) != 0)
10443 return (ISC_FALSE);
10444
10445 return (ISC_TRUE);
10446 }
10447
10448 isc_result_t
10449 ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) {
10450 dns_view_t *view;
10451 dns_ntatable_t *ntatable = NULL;
10452 isc_result_t result = ISC_R_SUCCESS;
10453 char *ptr, *nametext = NULL, *viewname;
10454 isc_stdtime_t now, when;
10455 isc_time_t t;
10456 char tbuf[64];
10457 const char *msg = NULL;
10458 isc_boolean_t dump = ISC_FALSE, force = ISC_FALSE;
10459 dns_fixedname_t fn;
10460 dns_name_t *ntaname;
10461 dns_ttl_t ntattl;
10462 isc_boolean_t ttlset = ISC_FALSE, excl = ISC_FALSE;
10463
10464 UNUSED(force);
10465
10466 dns_fixedname_init(&fn);
10467 ntaname = dns_fixedname_name(&fn);
10468
10469
10470 ptr = next_token(&args, " \t");
10471 if (ptr == NULL)
10472 return (ISC_R_UNEXPECTEDEND);
10473
10474 for (;;) {
10475
10476 ptr = next_token(&args, " \t");
10477 if (ptr == NULL)
10478 return (ISC_R_UNEXPECTEDEND);
10479
10480 if (argcheck(ptr, "dump"))
10481 dump = ISC_TRUE;
10482 else if (argcheck(ptr, "remove")) {
10483 ntattl = 0;
10484 ttlset = ISC_TRUE;
10485 } else if (argcheck(ptr, "force")) {
10486 force = ISC_TRUE;
10487 continue;
10488 } else if (argcheck(ptr, "lifetime")) {
10489 isc_textregion_t tr;
10490
10491 ptr = next_token(&args, " \t");
10492 if (ptr == NULL) {
10493 msg = "No lifetime specified";
10494 CHECK(ISC_R_UNEXPECTEDEND);
10495 }
10496
10497 tr.base = ptr;
10498 tr.length = strlen(ptr);
10499 result = dns_ttl_fromtext(&tr, &ntattl);
10500 if (result != ISC_R_SUCCESS) {
10501 msg = "could not parse NTA lifetime";
10502 CHECK(result);
10503 }
10504
10505 if (ntattl > 604800) {
10506 msg = "NTA lifetime cannot exceed one week";
10507 CHECK(ISC_R_RANGE);
10508 }
10509
10510 ttlset = ISC_TRUE;
10511 continue;
10512 } else
10513 nametext = ptr;
10514
10515 break;
10516 }
10517
10518
10519
10520
10521 if (dump) {
10522 for (view = ISC_LIST_HEAD(server->viewlist);
10523 view != NULL;
10524 view = ISC_LIST_NEXT(view, link))
10525 {
10526 if (ntatable != NULL)
10527 dns_ntatable_detach(&ntatable);
10528 result = dns_view_getntatable(view, &ntatable);
10529 if (result == ISC_R_NOTFOUND) {
10530 result = ISC_R_SUCCESS;
10531 continue;
10532 }
10533 CHECK(dns_ntatable_totext(ntatable, text));
10534 }
10535 CHECK(putnull(text));
10536
10537 goto cleanup;
10538 }
10539
10540
10541 if (nametext == NULL)
10542 nametext = next_token(&args, " \t");
10543 if (nametext == NULL)
10544 return (ISC_R_UNEXPECTEDEND);
10545
10546 if (strcmp(nametext, ".") == 0)
10547 ntaname = dns_rootname;
10548 else {
10549 isc_buffer_t b;
10550 isc_buffer_init(&b, nametext, strlen(nametext));
10551 isc_buffer_add(&b, strlen(nametext));
10552 CHECK(dns_name_fromtext(ntaname, &b, dns_rootname, 0, NULL));
10553 }
10554
10555
10556 viewname = next_token(&args, " \t");
10557
10558 isc_stdtime_get(&now);
10559
10560 result = isc_task_beginexclusive(server->task);
10561 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10562 excl = ISC_TRUE;
10563 for (view = ISC_LIST_HEAD(server->viewlist);
10564 view != NULL;
10565 view = ISC_LIST_NEXT(view, link))
10566 {
10567 if (viewname != NULL &&
10568 strcmp(view->name, viewname) != 0)
10569 continue;
10570
10571 if (view->nta_lifetime == 0)
10572 continue;
10573
10574 if (!ttlset)
10575 ntattl = view->nta_lifetime;
10576
10577 if (ntatable != NULL)
10578 dns_ntatable_detach(&ntatable);
10579
10580 result = dns_view_getntatable(view, &ntatable);
10581 if (result == ISC_R_NOTFOUND) {
10582 result = ISC_R_SUCCESS;
10583 continue;
10584 }
10585
10586 result = dns_view_flushnode(view, ntaname, ISC_TRUE);
10587 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
10588 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
10589 "flush tree '%s' in cache view '%s': %s",
10590 nametext, view->name,
10591 isc_result_totext(result));
10592
10593 if (ntattl != 0) {
10594 CHECK(dns_ntatable_add(ntatable, ntaname,
10595 force, now, ntattl));
10596
10597 when = now + ntattl;
10598 isc_time_set(&t, when, 0);
10599 isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
10600
10601 CHECK(putstr(text, "Negative trust anchor added: "));
10602 CHECK(putstr(text, nametext));
10603 CHECK(putstr(text, "/"));
10604 CHECK(putstr(text, view->name));
10605 CHECK(putstr(text, ", expires "));
10606 CHECK(putstr(text, tbuf));
10607
10608 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
10609 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
10610 "added NTA '%s' (%d sec) in view '%s'",
10611 nametext, ntattl, view->name);
10612 } else {
10613 CHECK(dns_ntatable_delete(ntatable, ntaname));
10614
10615 CHECK(putstr(text, "Negative trust anchor removed: "));
10616 CHECK(putstr(text, nametext));
10617 CHECK(putstr(text, "/"));
10618 CHECK(putstr(text, view->name));
10619
10620 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
10621 NS_LOGMODULE_SERVER, ISC_LOG_INFO,
10622 "removed NTA '%s' in view %s",
10623 nametext, view->name);
10624 }
10625
10626 result = dns_view_saventa(view);
10627 if (result != ISC_R_SUCCESS) {
10628 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
10629 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
10630 "error writing NTA file "
10631 "for view '%s': %s",
10632 view->name, isc_result_totext(result));
10633 }
10634
10635 CHECK(putnull(text));
10636
10637 }
10638
10639 cleanup:
10640 if (msg != NULL) {
10641 (void) putstr(text, msg);
10642 (void) putnull(text);
10643 }
10644 if (excl)
10645 isc_task_endexclusive(server->task);
10646 if (ntatable != NULL)
10647 dns_ntatable_detach(&ntatable);
10648 return (result);
10649 }
10650
10651 isc_result_t
10652 ns_server_saventa(ns_server_t *server) {
10653 dns_view_t *view;
10654
10655 for (view = ISC_LIST_HEAD(server->viewlist);
10656 view != NULL;
10657 view = ISC_LIST_NEXT(view, link))
10658 {
10659 isc_result_t result = dns_view_saventa(view);
10660
10661 if (result != ISC_R_SUCCESS) {
10662 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
10663 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
10664 "error writing NTA file "
10665 "for view '%s': %s",
10666 view->name, isc_result_totext(result));
10667 }
10668 }
10669
10670 return (ISC_R_SUCCESS);
10671 }
10672
10673 isc_result_t
10674 ns_server_loadnta(ns_server_t *server) {
10675 dns_view_t *view;
10676
10677 for (view = ISC_LIST_HEAD(server->viewlist);
10678 view != NULL;
10679 view = ISC_LIST_NEXT(view, link))
10680 {
10681 isc_result_t result = dns_view_loadnta(view);
10682
10683 if ((result != ISC_R_SUCCESS) &&
10684 (result != ISC_R_FILENOTFOUND) &&
10685 (result != ISC_R_NOTFOUND))
10686 {
10687 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
10688 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
10689 "error loading NTA file "
10690 "for view '%s': %s",
10691 view->name, isc_result_totext(result));
10692 }
10693 }
10694
10695 return (ISC_R_SUCCESS);
10696 }
10697
10698 static isc_result_t
10699 mkey_refresh(dns_view_t *view, isc_buffer_t **text) {
10700 isc_result_t result;
10701 char msg[DNS_NAME_FORMATSIZE + 500] = "";
10702
10703 snprintf(msg, sizeof(msg),
10704 "refreshing managed keys for '%s'", view->name);
10705 CHECK(putstr(text, msg));
10706 CHECK(dns_zone_synckeyzone(view->managed_keys));
10707
10708 cleanup:
10709 return (result);
10710 }
10711
10712 static isc_result_t
10713 mkey_dumpzone(dns_view_t *view, isc_buffer_t **text) {
10714 isc_result_t result;
10715 dns_db_t *db = NULL;
10716 dns_dbversion_t *ver = NULL;
10717 dns_rriterator_t rrit;
10718 isc_stdtime_t now;
10719 dns_name_t *prevname = NULL;
10720
10721 isc_stdtime_get(&now);
10722
10723 CHECK(dns_zone_getdb(view->managed_keys, &db));
10724 dns_db_currentversion(db, &ver);
10725 dns_rriterator_init(&rrit, db, ver, 0);
10726 for (result = dns_rriterator_first(&rrit);
10727 result == ISC_R_SUCCESS;
10728 result = dns_rriterator_nextrrset(&rrit))
10729 {
10730 char buf[DNS_NAME_FORMATSIZE + 500];
10731 dns_name_t *name = NULL;
10732 dns_rdataset_t *kdset = NULL;
10733 dns_rdata_t rdata = DNS_RDATA_INIT;
10734 dns_rdata_keydata_t kd;
10735 isc_uint32_t ttl;
10736
10737 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
10738 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
10739 !dns_rdataset_isassociated(kdset))
10740 continue;
10741
10742 if (name != prevname) {
10743 char nbuf[DNS_NAME_FORMATSIZE];
10744 dns_name_format(name, nbuf, sizeof(nbuf));
10745 snprintf(buf, sizeof(buf), "\n\n name: %s", nbuf);
10746 CHECK(putstr(text, buf));
10747 }
10748
10749
10750 for (result = dns_rdataset_first(kdset);
10751 result == ISC_R_SUCCESS;
10752 result = dns_rdataset_next(kdset))
10753 {
10754 char alg[DNS_SECALG_FORMATSIZE];
10755 char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
10756 dns_keytag_t keyid;
10757 isc_region_t r;
10758 isc_time_t t;
10759 isc_boolean_t revoked;
10760
10761 dns_rdata_reset(&rdata);
10762 dns_rdataset_current(kdset, &rdata);
10763 result = dns_rdata_tostruct(&rdata, &kd, NULL);
10764 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10765
10766 dns_rdata_toregion(&rdata, &r);
10767 isc_region_consume(&r, 12);
10768 keyid = dst_region_computeid(&r, kd.algorithm);
10769
10770 snprintf(buf, sizeof(buf), "\n keyid: %u", keyid);
10771 CHECK(putstr(text, buf));
10772
10773 dns_secalg_format(kd.algorithm, alg, sizeof(alg));
10774 snprintf(buf, sizeof(buf), "\n\talgorithm: %s", alg);
10775 CHECK(putstr(text, buf));
10776
10777 revoked = ISC_TF((kd.flags & DNS_KEYFLAG_REVOKE) != 0);
10778 snprintf(buf, sizeof(buf), "\n\tflags:%s%s%s",
10779 revoked ? " REVOKE" : "",
10780 ((kd.flags & DNS_KEYFLAG_KSK) != 0)
10781 ? " SEP" : "",
10782 (kd.flags == 0) ? " (none)" : "");
10783 CHECK(putstr(text, buf));
10784
10785 isc_time_set(&t, kd.refresh, 0);
10786 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf));
10787 snprintf(buf, sizeof(buf),
10788 "\n\tnext refresh: %s", tbuf);
10789 CHECK(putstr(text, buf));
10790
10791 if (kd.removehd != 0) {
10792 isc_time_set(&t, kd.removehd, 0);
10793 isc_time_formathttptimestamp(&t, tbuf,
10794 sizeof(tbuf));
10795 snprintf(buf, sizeof(buf),
10796 "\n\tremove at: %s", tbuf);
10797 CHECK(putstr(text, buf));
10798 }
10799
10800 isc_time_set(&t, kd.addhd, 0);
10801 isc_time_formathttptimestamp(&t, tbuf, sizeof(tbuf));
10802 if (kd.addhd == 0)
10803 snprintf(buf, sizeof(buf), "\n\tno trust");
10804 else if (revoked)
10805 snprintf(buf, sizeof(buf),
10806 "\n\ttrust revoked");
10807 else if (kd.addhd < now)
10808 snprintf(buf, sizeof(buf),
10809 "\n\ttrusted since: %s", tbuf);
10810 else if (kd.addhd >= now)
10811 snprintf(buf, sizeof(buf),
10812 "\n\ttrust pending: %s", tbuf);
10813 CHECK(putstr(text, buf));
10814 }
10815 }
10816
10817 if (result == ISC_R_NOMORE)
10818 result = ISC_R_SUCCESS;
10819
10820 cleanup:
10821 if (ver != NULL) {
10822 dns_rriterator_destroy(&rrit);
10823 dns_db_closeversion(db, &ver, ISC_FALSE);
10824 }
10825 if (db != NULL)
10826 dns_db_detach(&db);
10827
10828 return (result);
10829 }
10830
10831 static isc_result_t
10832 mkey_status(dns_view_t *view, isc_buffer_t **text) {
10833 isc_result_t result;
10834 char msg[ISC_FORMATHTTPTIMESTAMP_SIZE];
10835 isc_time_t t;
10836
10837 CHECK(putstr(text, "view: "));
10838 CHECK(putstr(text, view->name));
10839
10840 CHECK(putstr(text, "\nnext scheduled event: "));
10841
10842 dns_zone_getrefreshkeytime(view->managed_keys, &t);
10843 if (isc_time_isepoch(&t)) {
10844 CHECK(putstr(text, "never"));
10845 } else {
10846 isc_time_formathttptimestamp(&t, msg, sizeof(msg));
10847 CHECK(putstr(text, msg));
10848 }
10849
10850 CHECK(mkey_dumpzone(view, text));
10851
10852 cleanup:
10853 return (result);
10854 }
10855
10856 isc_result_t
10857 ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text) {
10858 char *cmd, *classtxt, *viewtxt = NULL;
10859 isc_result_t result = ISC_R_SUCCESS;
10860 dns_view_t *view = NULL;
10861 dns_rdataclass_t rdclass;
10862 char msg[DNS_NAME_FORMATSIZE + 500] = "";
10863 enum { NONE, STATUS, REFRESH, SYNC } opt = NONE;
10864 isc_boolean_t found = ISC_FALSE;
10865 isc_boolean_t first = ISC_TRUE;
10866
10867
10868 cmd = next_token(&args, " \t");
10869 if (cmd == NULL)
10870 return (ISC_R_UNEXPECTEDEND);
10871
10872
10873 cmd = next_token(&args, " \t");
10874 if (cmd == NULL)
10875 return (ISC_R_UNEXPECTEDEND);
10876
10877 if (strcasecmp(cmd, "status") == 0)
10878 opt = STATUS;
10879 else if (strcasecmp(cmd, "refresh") == 0)
10880 opt = REFRESH;
10881 else if (strcasecmp(cmd, "sync") == 0)
10882 opt = SYNC;
10883 else {
10884 snprintf(msg, sizeof(msg), "unknown command '%s'", cmd);
10885 (void) putstr(text, msg);
10886 result = ISC_R_UNEXPECTED;
10887 goto cleanup;
10888 }
10889
10890
10891 classtxt = next_token(&args, " \t");
10892 if (classtxt != NULL) {
10893
10894 viewtxt = next_token(&args, " \t");
10895 }
10896
10897 if (classtxt == NULL) {
10898 rdclass = dns_rdataclass_in;
10899 } else {
10900 isc_textregion_t r;
10901 r.base = classtxt;
10902 r.length = strlen(classtxt);
10903 result = dns_rdataclass_fromtext(&rdclass, &r);
10904 if (result != ISC_R_SUCCESS) {
10905 if (viewtxt == NULL) {
10906 rdclass = dns_rdataclass_in;
10907 viewtxt = classtxt;
10908 result = ISC_R_SUCCESS;
10909 } else {
10910 snprintf(msg, sizeof(msg),
10911 "unknown class '%s'", classtxt);
10912 (void) putstr(text, msg);
10913 goto cleanup;
10914 }
10915 }
10916 }
10917
10918 for (view = ISC_LIST_HEAD(server->viewlist);
10919 view != NULL;
10920 view = ISC_LIST_NEXT(view, link))
10921 {
10922 if (viewtxt != NULL &&
10923 (rdclass != view->rdclass ||
10924 strcmp(view->name, viewtxt) != 0))
10925 continue;
10926
10927 if (view->managed_keys == NULL) {
10928 if (viewtxt != NULL) {
10929 snprintf(msg, sizeof(msg),
10930 "view '%s': no managed keys", viewtxt);
10931 CHECK(putstr(text, msg));
10932 goto cleanup;
10933 } else
10934 continue;
10935 }
10936
10937 found = ISC_TRUE;
10938
10939 switch (opt) {
10940 case REFRESH:
10941 CHECK(mkey_refresh(view, text));
10942 break;
10943 case STATUS:
10944 if (!first)
10945 CHECK(putstr(text, "\n\n"));
10946 CHECK(mkey_status(view, text));
10947 first = ISC_FALSE;
10948 break;
10949 case SYNC:
10950 CHECK(dns_zone_flush(view->managed_keys));
10951 break;
10952 default:
10953 INSIST(0);
10954 }
10955
10956 if (viewtxt != NULL)
10957 break;
10958 }
10959
10960 if (!found)
10961 CHECK(putstr(text, "no views with managed keys"));
10962
10963 cleanup:
10964 if (isc_buffer_usedlength(*text) > 0)
10965 (void) putnull(text);
10966
10967 return (result);
10968 }