~ubuntu-branches/ubuntu/natty/bind9/natty-security

« back to all changes in this revision

Viewing changes to .pc/debian-changes-1:9.7.1.dfsg-2/bin/named/server.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2010-07-15 17:11:12 UTC
  • mfrom: (1.6.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20100715171112-t30mndas2k8o0pwn
Tags: 1:9.7.1.dfsg.P2-1~build1
ubuntu upload to speed things along

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2004-2010  Internet Systems Consortium, Inc. ("ISC")
3
 
 * Copyright (C) 1999-2003  Internet Software Consortium.
4
 
 *
5
 
 * Permission to use, copy, modify, and/or distribute this software for any
6
 
 * purpose with or without fee is hereby granted, provided that the above
7
 
 * copyright notice and this permission notice appear in all copies.
8
 
 *
9
 
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10
 
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
 
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12
 
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
 
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
 
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
 
 * PERFORMANCE OF THIS SOFTWARE.
16
 
 */
17
 
 
18
 
/* $Id: server.c,v 1.556.8.12 2010/05/18 00:29:31 marka Exp $ */
19
 
 
20
 
/*! \file */
21
 
 
22
 
#include <config.h>
23
 
 
24
 
#include <stdlib.h>
25
 
#include <unistd.h>
26
 
#include <limits.h>
27
 
 
28
 
#include <isc/app.h>
29
 
#include <isc/base64.h>
30
 
#include <isc/dir.h>
31
 
#include <isc/entropy.h>
32
 
#include <isc/file.h>
33
 
#include <isc/hash.h>
34
 
#include <isc/httpd.h>
35
 
#include <isc/lex.h>
36
 
#include <isc/parseint.h>
37
 
#include <isc/portset.h>
38
 
#include <isc/print.h>
39
 
#include <isc/resource.h>
40
 
#include <isc/sha2.h>
41
 
#include <isc/socket.h>
42
 
#include <isc/stat.h>
43
 
#include <isc/stats.h>
44
 
#include <isc/stdio.h>
45
 
#include <isc/string.h>
46
 
#include <isc/task.h>
47
 
#include <isc/timer.h>
48
 
#include <isc/util.h>
49
 
#include <isc/xml.h>
50
 
 
51
 
#include <isccfg/namedconf.h>
52
 
 
53
 
#include <bind9/check.h>
54
 
 
55
 
#include <dns/acache.h>
56
 
#include <dns/adb.h>
57
 
#include <dns/cache.h>
58
 
#include <dns/db.h>
59
 
#include <dns/dispatch.h>
60
 
#ifdef DLZ
61
 
#include <dns/dlz.h>
62
 
#endif
63
 
#include <dns/forward.h>
64
 
#include <dns/journal.h>
65
 
#include <dns/keytable.h>
66
 
#include <dns/keyvalues.h>
67
 
#include <dns/lib.h>
68
 
#include <dns/master.h>
69
 
#include <dns/masterdump.h>
70
 
#include <dns/order.h>
71
 
#include <dns/peer.h>
72
 
#include <dns/portlist.h>
73
 
#include <dns/rbt.h>
74
 
#include <dns/rdataclass.h>
75
 
#include <dns/rdataset.h>
76
 
#include <dns/rdatastruct.h>
77
 
#include <dns/resolver.h>
78
 
#include <dns/rootns.h>
79
 
#include <dns/secalg.h>
80
 
#include <dns/stats.h>
81
 
#include <dns/tkey.h>
82
 
#include <dns/tsig.h>
83
 
#include <dns/view.h>
84
 
#include <dns/zone.h>
85
 
#include <dns/zt.h>
86
 
 
87
 
#include <dst/dst.h>
88
 
#include <dst/result.h>
89
 
 
90
 
#include <named/client.h>
91
 
#include <named/config.h>
92
 
#include <named/control.h>
93
 
#include <named/interfacemgr.h>
94
 
#include <named/log.h>
95
 
#include <named/logconf.h>
96
 
#include <named/lwresd.h>
97
 
#include <named/main.h>
98
 
#include <named/os.h>
99
 
#include <named/server.h>
100
 
#include <named/statschannel.h>
101
 
#include <named/tkeyconf.h>
102
 
#include <named/tsigconf.h>
103
 
#include <named/zoneconf.h>
104
 
#ifdef HAVE_LIBSCF
105
 
#include <named/ns_smf_globals.h>
106
 
#include <stdlib.h>
107
 
#endif
108
 
 
109
 
#ifndef PATH_MAX
110
 
#define PATH_MAX 1024
111
 
#endif
112
 
 
113
 
/*%
114
 
 * Check an operation for failure.  Assumes that the function
115
 
 * using it has a 'result' variable and a 'cleanup' label.
116
 
 */
117
 
#define CHECK(op) \
118
 
        do { result = (op);                                      \
119
 
               if (result != ISC_R_SUCCESS) goto cleanup;        \
120
 
        } while (0)
121
 
 
122
 
#define CHECKM(op, msg) \
123
 
        do { result = (op);                                       \
124
 
               if (result != ISC_R_SUCCESS) {                     \
125
 
                        isc_log_write(ns_g_lctx,                  \
126
 
                                      NS_LOGCATEGORY_GENERAL,     \
127
 
                                      NS_LOGMODULE_SERVER,        \
128
 
                                      ISC_LOG_ERROR,              \
129
 
                                      "%s: %s", msg,              \
130
 
                                      isc_result_totext(result)); \
131
 
                        goto cleanup;                             \
132
 
                }                                                 \
133
 
        } while (0)                                               \
134
 
 
135
 
#define CHECKMF(op, msg, file) \
136
 
        do { result = (op);                                       \
137
 
               if (result != ISC_R_SUCCESS) {                     \
138
 
                        isc_log_write(ns_g_lctx,                  \
139
 
                                      NS_LOGCATEGORY_GENERAL,     \
140
 
                                      NS_LOGMODULE_SERVER,        \
141
 
                                      ISC_LOG_ERROR,              \
142
 
                                      "%s '%s': %s", msg, file,   \
143
 
                                      isc_result_totext(result)); \
144
 
                        goto cleanup;                             \
145
 
                }                                                 \
146
 
        } while (0)                                               \
147
 
 
148
 
#define CHECKFATAL(op, msg) \
149
 
        do { result = (op);                                       \
150
 
               if (result != ISC_R_SUCCESS)                       \
151
 
                        fatal(msg, result);                       \
152
 
        } while (0)                                               \
153
 
 
154
 
/*%
155
 
 * Maximum ADB size for views that share a cache.  Use this limit to suppress
156
 
 * the total of memory footprint, which should be the main reason for sharing
157
 
 * a cache.  Only effective when a finite max-cache-size is specified.
158
 
 * This is currently defined to be 8MB.
159
 
 */
160
 
#define MAX_ADB_SIZE_FOR_CACHESHARE     8388608
161
 
 
162
 
struct ns_dispatch {
163
 
        isc_sockaddr_t                  addr;
164
 
        unsigned int                    dispatchgen;
165
 
        dns_dispatch_t                  *dispatch;
166
 
        ISC_LINK(struct ns_dispatch)    link;
167
 
};
168
 
 
169
 
struct ns_cache {
170
 
        dns_cache_t                     *cache;
171
 
        dns_view_t                      *primaryview;
172
 
        isc_boolean_t                   needflush;
173
 
        isc_boolean_t                   adbsizeadjusted;
174
 
        ISC_LINK(ns_cache_t)            link;
175
 
};
176
 
 
177
 
struct dumpcontext {
178
 
        isc_mem_t                       *mctx;
179
 
        isc_boolean_t                   dumpcache;
180
 
        isc_boolean_t                   dumpzones;
181
 
        FILE                            *fp;
182
 
        ISC_LIST(struct viewlistentry)  viewlist;
183
 
        struct viewlistentry            *view;
184
 
        struct zonelistentry            *zone;
185
 
        dns_dumpctx_t                   *mdctx;
186
 
        dns_db_t                        *db;
187
 
        dns_db_t                        *cache;
188
 
        isc_task_t                      *task;
189
 
        dns_dbversion_t                 *version;
190
 
};
191
 
 
192
 
struct viewlistentry {
193
 
        dns_view_t                      *view;
194
 
        ISC_LINK(struct viewlistentry)  link;
195
 
        ISC_LIST(struct zonelistentry)  zonelist;
196
 
};
197
 
 
198
 
struct zonelistentry {
199
 
        dns_zone_t                      *zone;
200
 
        ISC_LINK(struct zonelistentry)  link;
201
 
};
202
 
 
203
 
/*
204
 
 * These zones should not leak onto the Internet.
205
 
 */
206
 
static const struct {
207
 
        const char      *zone;
208
 
        isc_boolean_t   rfc1918;
209
 
} empty_zones[] = {
210
 
#ifdef notyet
211
 
        /* RFC 1918 */
212
 
        { "10.IN-ADDR.ARPA", ISC_TRUE },
213
 
        { "16.172.IN-ADDR.ARPA", ISC_TRUE },
214
 
        { "17.172.IN-ADDR.ARPA", ISC_TRUE },
215
 
        { "18.172.IN-ADDR.ARPA", ISC_TRUE },
216
 
        { "19.172.IN-ADDR.ARPA", ISC_TRUE },
217
 
        { "20.172.IN-ADDR.ARPA", ISC_TRUE },
218
 
        { "21.172.IN-ADDR.ARPA", ISC_TRUE },
219
 
        { "22.172.IN-ADDR.ARPA", ISC_TRUE },
220
 
        { "23.172.IN-ADDR.ARPA", ISC_TRUE },
221
 
        { "24.172.IN-ADDR.ARPA", ISC_TRUE },
222
 
        { "25.172.IN-ADDR.ARPA", ISC_TRUE },
223
 
        { "26.172.IN-ADDR.ARPA", ISC_TRUE },
224
 
        { "27.172.IN-ADDR.ARPA", ISC_TRUE },
225
 
        { "28.172.IN-ADDR.ARPA", ISC_TRUE },
226
 
        { "29.172.IN-ADDR.ARPA", ISC_TRUE },
227
 
        { "30.172.IN-ADDR.ARPA", ISC_TRUE },
228
 
        { "31.172.IN-ADDR.ARPA", ISC_TRUE },
229
 
        { "168.192.IN-ADDR.ARPA", ISC_TRUE },
230
 
#endif
231
 
 
232
 
        /* RFC 5735 and RFC 5737 */
233
 
        { "0.IN-ADDR.ARPA", ISC_FALSE },        /* THIS NETWORK */
234
 
        { "127.IN-ADDR.ARPA", ISC_FALSE },      /* LOOPBACK */
235
 
        { "254.169.IN-ADDR.ARPA", ISC_FALSE },  /* LINK LOCAL */
236
 
        { "2.0.192.IN-ADDR.ARPA", ISC_FALSE },  /* TEST NET */
237
 
        { "100.51.198.IN-ADDR.ARPA", ISC_FALSE },       /* TEST NET 2 */
238
 
        { "113.0.203.IN-ADDR.ARPA", ISC_FALSE },        /* TEST NET 3 */
239
 
        { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE },  /* BROADCAST */
240
 
 
241
 
        /* Local IPv6 Unicast Addresses */
242
 
        { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
243
 
        { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
244
 
        /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */
245
 
        { "D.F.IP6.ARPA", ISC_FALSE },
246
 
        { "8.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
247
 
        { "9.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
248
 
        { "A.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
249
 
        { "B.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
250
 
 
251
 
        /* Example Prefix, RFC 3849. */
252
 
        { "8.B.D.0.1.0.0.2.IP6.ARPA", ISC_FALSE },
253
 
 
254
 
        /* ORCHID Prefix, RFC 4843. */
255
 
        { "0.1.1.0.0.2.IP6.ARPA", ISC_FALSE },
256
 
 
257
 
        { NULL, ISC_FALSE }
258
 
};
259
 
 
260
 
ISC_PLATFORM_NORETURN_PRE static void
261
 
fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
262
 
 
263
 
static void
264
 
ns_server_reload(isc_task_t *task, isc_event_t *event);
265
 
 
266
 
static isc_result_t
267
 
ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
268
 
                        cfg_aclconfctx_t *actx,
269
 
                        isc_mem_t *mctx, ns_listenelt_t **target);
270
 
static isc_result_t
271
 
ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
272
 
                         cfg_aclconfctx_t *actx,
273
 
                         isc_mem_t *mctx, ns_listenlist_t **target);
274
 
 
275
 
static isc_result_t
276
 
configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
277
 
                  const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype);
278
 
 
279
 
static isc_result_t
280
 
configure_alternates(const cfg_obj_t *config, dns_view_t *view,
281
 
                     const cfg_obj_t *alternates);
282
 
 
283
 
static isc_result_t
284
 
configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
285
 
               const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
286
 
               cfg_aclconfctx_t *aclconf);
287
 
 
288
 
static isc_result_t
289
 
add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx);
290
 
 
291
 
static void
292
 
end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
293
 
 
294
 
/*%
295
 
 * Configure a single view ACL at '*aclp'.  Get its configuration from
296
 
 * 'vconfig' (for per-view configuration) and maybe from 'config'
297
 
 */
298
 
static isc_result_t
299
 
configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
300
 
                   const char *aclname, const char *acltuplename,
301
 
                   cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp)
302
 
{
303
 
        isc_result_t result;
304
 
        const cfg_obj_t *maps[3];
305
 
        const cfg_obj_t *aclobj = NULL;
306
 
        int i = 0;
307
 
 
308
 
        if (*aclp != NULL)
309
 
                dns_acl_detach(aclp);
310
 
        if (vconfig != NULL)
311
 
                maps[i++] = cfg_tuple_get(vconfig, "options");
312
 
        if (config != NULL) {
313
 
                const cfg_obj_t *options = NULL;
314
 
                (void)cfg_map_get(config, "options", &options);
315
 
                if (options != NULL)
316
 
                        maps[i++] = options;
317
 
        }
318
 
        maps[i] = NULL;
319
 
 
320
 
        (void)ns_config_get(maps, aclname, &aclobj);
321
 
        if (aclobj == NULL)
322
 
                /*
323
 
                 * No value available.  *aclp == NULL.
324
 
                 */
325
 
                return (ISC_R_SUCCESS);
326
 
 
327
 
        if (acltuplename != NULL) {
328
 
                /*
329
 
                 * If the ACL is given in an optional tuple, retrieve it.
330
 
                 * The parser should have ensured that a valid object be
331
 
                 * returned.
332
 
                 */
333
 
                aclobj = cfg_tuple_get(aclobj, acltuplename);
334
 
        }
335
 
 
336
 
        result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
337
 
                                    actx, mctx, 0, aclp);
338
 
 
339
 
        return (result);
340
 
}
341
 
 
342
 
/*%
343
 
 * Configure a sortlist at '*aclp'.  Essentially the same as
344
 
 * configure_view_acl() except it calls cfg_acl_fromconfig with a
345
 
 * nest_level value of 2.
346
 
 */
347
 
static isc_result_t
348
 
configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
349
 
                        cfg_aclconfctx_t *actx, isc_mem_t *mctx,
350
 
                        dns_acl_t **aclp)
351
 
{
352
 
        isc_result_t result;
353
 
        const cfg_obj_t *maps[3];
354
 
        const cfg_obj_t *aclobj = NULL;
355
 
        int i = 0;
356
 
 
357
 
        if (*aclp != NULL)
358
 
                dns_acl_detach(aclp);
359
 
        if (vconfig != NULL)
360
 
                maps[i++] = cfg_tuple_get(vconfig, "options");
361
 
        if (config != NULL) {
362
 
                const cfg_obj_t *options = NULL;
363
 
                (void)cfg_map_get(config, "options", &options);
364
 
                if (options != NULL)
365
 
                        maps[i++] = options;
366
 
        }
367
 
        maps[i] = NULL;
368
 
 
369
 
        (void)ns_config_get(maps, "sortlist", &aclobj);
370
 
        if (aclobj == NULL)
371
 
                return (ISC_R_SUCCESS);
372
 
 
373
 
        /*
374
 
         * Use a nest level of 3 for the "top level" of the sortlist;
375
 
         * this means each entry in the top three levels will be stored
376
 
         * as lists of separate, nested ACLs, rather than merged together
377
 
         * into IP tables as is usually done with ACLs.
378
 
         */
379
 
        result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
380
 
                                    actx, mctx, 3, aclp);
381
 
 
382
 
        return (result);
383
 
}
384
 
 
385
 
static isc_result_t
386
 
configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
387
 
                         const char *confname, const char *conftuplename,
388
 
                         isc_mem_t *mctx, dns_rbt_t **rbtp)
389
 
{
390
 
        isc_result_t result;
391
 
        const cfg_obj_t *maps[3];
392
 
        const cfg_obj_t *obj = NULL;
393
 
        const cfg_listelt_t *element;
394
 
        int i = 0;
395
 
        dns_fixedname_t fixed;
396
 
        dns_name_t *name;
397
 
        isc_buffer_t b;
398
 
        const char *str;
399
 
        const cfg_obj_t *nameobj;
400
 
 
401
 
        if (*rbtp != NULL)
402
 
                dns_rbt_destroy(rbtp);
403
 
        if (vconfig != NULL)
404
 
                maps[i++] = cfg_tuple_get(vconfig, "options");
405
 
        if (config != NULL) {
406
 
                const cfg_obj_t *options = NULL;
407
 
                (void)cfg_map_get(config, "options", &options);
408
 
                if (options != NULL)
409
 
                        maps[i++] = options;
410
 
        }
411
 
        maps[i] = NULL;
412
 
 
413
 
        (void)ns_config_get(maps, confname, &obj);
414
 
        if (obj == NULL)
415
 
                /*
416
 
                 * No value available.  *rbtp == NULL.
417
 
                 */
418
 
                return (ISC_R_SUCCESS);
419
 
 
420
 
        if (conftuplename != NULL) {
421
 
                obj = cfg_tuple_get(obj, conftuplename);
422
 
                if (cfg_obj_isvoid(obj))
423
 
                        return (ISC_R_SUCCESS);
424
 
        }
425
 
 
426
 
        result = dns_rbt_create(mctx, NULL, NULL, rbtp);
427
 
        if (result != ISC_R_SUCCESS)
428
 
                return (result);
429
 
 
430
 
        dns_fixedname_init(&fixed);
431
 
        name = dns_fixedname_name(&fixed);
432
 
        for (element = cfg_list_first(obj);
433
 
             element != NULL;
434
 
             element = cfg_list_next(element)) {
435
 
                nameobj = cfg_listelt_value(element);
436
 
                str = cfg_obj_asstring(nameobj);
437
 
                isc_buffer_init(&b, str, strlen(str));
438
 
                isc_buffer_add(&b, strlen(str));
439
 
                CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
440
 
                /*
441
 
                 * We don't need the node data, but need to set dummy data to
442
 
                 * avoid a partial match with an empty node.  For example, if
443
 
                 * we have foo.example.com and bar.example.com, we'd get a match
444
 
                 * for baz.example.com, which is not the expected result.
445
 
                 * We simply use (void *)1 as the dummy data.
446
 
                 */
447
 
                result = dns_rbt_addname(*rbtp, name, (void *)1);
448
 
                if (result != ISC_R_SUCCESS) {
449
 
                        cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR,
450
 
                                    "failed to add %s for %s: %s",
451
 
                                    str, confname, isc_result_totext(result));
452
 
                        goto cleanup;
453
 
                }
454
 
 
455
 
        }
456
 
 
457
 
        return (result);
458
 
 
459
 
  cleanup:
460
 
        dns_rbt_destroy(rbtp);
461
 
        return (result);
462
 
 
463
 
}
464
 
 
465
 
static isc_result_t
466
 
dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
467
 
                  isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx)
468
 
{
469
 
        dns_rdataclass_t viewclass;
470
 
        dns_rdata_dnskey_t keystruct;
471
 
        isc_uint32_t flags, proto, alg;
472
 
        const char *keystr, *keynamestr;
473
 
        unsigned char keydata[4096];
474
 
        isc_buffer_t keydatabuf;
475
 
        unsigned char rrdata[4096];
476
 
        isc_buffer_t rrdatabuf;
477
 
        isc_region_t r;
478
 
        dns_fixedname_t fkeyname;
479
 
        dns_name_t *keyname;
480
 
        isc_buffer_t namebuf;
481
 
        isc_result_t result;
482
 
        dst_key_t *dstkey = NULL;
483
 
 
484
 
        INSIST(target != NULL && *target == NULL);
485
 
 
486
 
        flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
487
 
        proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
488
 
        alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
489
 
        keyname = dns_fixedname_name(&fkeyname);
490
 
        keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
491
 
 
492
 
        if (managed) {
493
 
                const char *initmethod;
494
 
                initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
495
 
 
496
 
                if (strcasecmp(initmethod, "initial-key") != 0) {
497
 
                        cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
498
 
                                    "managed key '%s': "
499
 
                                    "invalid initialization method '%s'",
500
 
                                    keynamestr, initmethod);
501
 
                        result = ISC_R_FAILURE;
502
 
                        goto cleanup;
503
 
                }
504
 
        }
505
 
 
506
 
        if (vconfig == NULL)
507
 
                viewclass = dns_rdataclass_in;
508
 
        else {
509
 
                const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
510
 
                CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
511
 
                                         &viewclass));
512
 
        }
513
 
        keystruct.common.rdclass = viewclass;
514
 
        keystruct.common.rdtype = dns_rdatatype_dnskey;
515
 
        /*
516
 
         * The key data in keystruct is not dynamically allocated.
517
 
         */
518
 
        keystruct.mctx = NULL;
519
 
 
520
 
        ISC_LINK_INIT(&keystruct.common, link);
521
 
 
522
 
        if (flags > 0xffff)
523
 
                CHECKM(ISC_R_RANGE, "key flags");
524
 
        if (proto > 0xff)
525
 
                CHECKM(ISC_R_RANGE, "key protocol");
526
 
        if (alg > 0xff)
527
 
                CHECKM(ISC_R_RANGE, "key algorithm");
528
 
        keystruct.flags = (isc_uint16_t)flags;
529
 
        keystruct.protocol = (isc_uint8_t)proto;
530
 
        keystruct.algorithm = (isc_uint8_t)alg;
531
 
 
532
 
        isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
533
 
        isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
534
 
 
535
 
        keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
536
 
        CHECK(isc_base64_decodestring(keystr, &keydatabuf));
537
 
        isc_buffer_usedregion(&keydatabuf, &r);
538
 
        keystruct.datalen = r.length;
539
 
        keystruct.data = r.base;
540
 
 
541
 
        if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
542
 
             keystruct.algorithm == DST_ALG_RSAMD5) &&
543
 
            r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
544
 
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
545
 
                            "%s key '%s' has a weak exponent",
546
 
                            managed ? "managed" : "trusted",
547
 
                            keynamestr);
548
 
 
549
 
        CHECK(dns_rdata_fromstruct(NULL,
550
 
                                   keystruct.common.rdclass,
551
 
                                   keystruct.common.rdtype,
552
 
                                   &keystruct, &rrdatabuf));
553
 
        dns_fixedname_init(&fkeyname);
554
 
        isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr));
555
 
        isc_buffer_add(&namebuf, strlen(keynamestr));
556
 
        CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
557
 
        CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
558
 
                              mctx, &dstkey));
559
 
 
560
 
        *target = dstkey;
561
 
        return (ISC_R_SUCCESS);
562
 
 
563
 
 cleanup:
564
 
        if (result == DST_R_NOCRYPTO) {
565
 
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
566
 
                            "ignoring %s key for '%s': no crypto support",
567
 
                            managed ? "managed" : "trusted",
568
 
                            keynamestr);
569
 
        } else if (result == DST_R_UNSUPPORTEDALG) {
570
 
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
571
 
                            "skipping %s key for '%s': %s",
572
 
                            managed ? "managed" : "trusted",
573
 
                            keynamestr, isc_result_totext(result));
574
 
        } else {
575
 
                cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
576
 
                            "configuring %s key for '%s': %s",
577
 
                            managed ? "managed" : "trusted",
578
 
                            keynamestr, isc_result_totext(result));
579
 
                result = ISC_R_FAILURE;
580
 
        }
581
 
 
582
 
        if (dstkey != NULL)
583
 
                dst_key_free(&dstkey);
584
 
 
585
 
        return (result);
586
 
}
587
 
 
588
 
static isc_result_t
589
 
load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
590
 
               dns_view_t *view, isc_boolean_t managed, isc_mem_t *mctx)
591
 
{
592
 
        const cfg_listelt_t *elt, *elt2;
593
 
        const cfg_obj_t *key, *keylist;
594
 
        dst_key_t *dstkey = NULL;
595
 
        isc_result_t result;
596
 
        dns_keytable_t *secroots = NULL;
597
 
 
598
 
        CHECK(dns_view_getsecroots(view, &secroots));
599
 
 
600
 
        for (elt = cfg_list_first(keys);
601
 
             elt != NULL;
602
 
             elt = cfg_list_next(elt)) {
603
 
                keylist = cfg_listelt_value(elt);
604
 
 
605
 
                for (elt2 = cfg_list_first(keylist);
606
 
                     elt2 != NULL;
607
 
                     elt2 = cfg_list_next(elt2)) {
608
 
                        key = cfg_listelt_value(elt2);
609
 
                        result = dstkey_fromconfig(vconfig, key, managed,
610
 
                                                   &dstkey, mctx);
611
 
                        if (result ==  DST_R_UNSUPPORTEDALG) {
612
 
                                result = ISC_R_SUCCESS;
613
 
                                continue;
614
 
                        }
615
 
                        if (result != ISC_R_SUCCESS)
616
 
                                goto cleanup;
617
 
 
618
 
                        CHECK(dns_keytable_add(secroots, managed, &dstkey));
619
 
                }
620
 
        }
621
 
 
622
 
 cleanup:
623
 
        if (secroots != NULL)
624
 
                dns_keytable_detach(&secroots);
625
 
        if (result == DST_R_NOCRYPTO)
626
 
                result = ISC_R_SUCCESS;
627
 
        return (result);
628
 
}
629
 
 
630
 
/*%
631
 
 * Configure DNSSEC keys for a view.
632
 
 *
633
 
 * The per-view configuration values and the server-global defaults are read
634
 
 * from 'vconfig' and 'config'.
635
 
 */
636
 
static isc_result_t
637
 
configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
638
 
                          const cfg_obj_t *config, const cfg_obj_t *bindkeys,
639
 
                          isc_boolean_t auto_dlv, isc_mem_t *mctx)
640
 
{
641
 
        isc_result_t result = ISC_R_SUCCESS;
642
 
        const cfg_obj_t *view_keys = NULL;
643
 
        const cfg_obj_t *global_keys = NULL;
644
 
        const cfg_obj_t *view_managed_keys = NULL;
645
 
        const cfg_obj_t *global_managed_keys = NULL;
646
 
        const cfg_obj_t *builtin_keys = NULL;
647
 
        const cfg_obj_t *builtin_managed_keys = NULL;
648
 
        const cfg_obj_t *maps[4];
649
 
        const cfg_obj_t *voptions = NULL;
650
 
        const cfg_obj_t *options = NULL;
651
 
        const cfg_obj_t *obj = NULL;
652
 
        const char *directory;
653
 
        int i = 0;
654
 
 
655
 
        /* We don't need trust anchors for the _bind view */
656
 
        if (strcmp(view->name, "_bind") == 0 &&
657
 
            view->rdclass == dns_rdataclass_chaos) {
658
 
                return (ISC_R_SUCCESS);
659
 
        }
660
 
 
661
 
        if (vconfig != NULL) {
662
 
                voptions = cfg_tuple_get(vconfig, "options");
663
 
                if (voptions != NULL) {
664
 
                        (void) cfg_map_get(voptions, "trusted-keys",
665
 
                                           &view_keys);
666
 
                        (void) cfg_map_get(voptions, "managed-keys",
667
 
                                           &view_managed_keys);
668
 
                        maps[i++] = voptions;
669
 
                }
670
 
        }
671
 
 
672
 
        if (config != NULL) {
673
 
                (void)cfg_map_get(config, "trusted-keys", &global_keys);
674
 
                (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
675
 
                (void)cfg_map_get(config, "options", &options);
676
 
                if (options != NULL) {
677
 
                        maps[i++] = options;
678
 
                }
679
 
        }
680
 
 
681
 
        maps[i++] = ns_g_defaults;
682
 
        maps[i] = NULL;
683
 
 
684
 
        result = dns_view_initsecroots(view, mctx);
685
 
        if (result != ISC_R_SUCCESS) {
686
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
687
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
688
 
                              "couldn't create keytable");
689
 
                return (ISC_R_UNEXPECTED);
690
 
        }
691
 
 
692
 
        if (auto_dlv && view->rdclass == dns_rdataclass_in) {
693
 
                isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
694
 
                              NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
695
 
                              "using built-in trusted-keys for view %s",
696
 
                              view->name);
697
 
 
698
 
                /*
699
 
                 * If bind.keys exists, it overrides the managed-keys
700
 
                 * clause hard-coded in ns_g_config.
701
 
                 */
702
 
                if (bindkeys != NULL) {
703
 
                        (void)cfg_map_get(bindkeys, "trusted-keys",
704
 
                                          &builtin_keys);
705
 
                        (void)cfg_map_get(bindkeys, "managed-keys",
706
 
                                          &builtin_managed_keys);
707
 
                } else {
708
 
                        (void)cfg_map_get(ns_g_config, "trusted-keys",
709
 
                                          &builtin_keys);
710
 
                        (void)cfg_map_get(ns_g_config, "managed-keys",
711
 
                                          &builtin_managed_keys);
712
 
                }
713
 
 
714
 
                if (builtin_keys != NULL)
715
 
                        CHECK(load_view_keys(builtin_keys, vconfig, view,
716
 
                                             ISC_FALSE, mctx));
717
 
                if (builtin_managed_keys != NULL)
718
 
                        CHECK(load_view_keys(builtin_managed_keys, vconfig,
719
 
                                             view, ISC_TRUE, mctx));
720
 
        }
721
 
 
722
 
        CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE, mctx));
723
 
        CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE, mctx));
724
 
        if (view->rdclass == dns_rdataclass_in) {
725
 
                CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE,
726
 
                                     mctx));
727
 
                CHECK(load_view_keys(global_managed_keys, vconfig, view,
728
 
                                     ISC_TRUE, mctx));
729
 
        }
730
 
 
731
 
        /*
732
 
         * Add key zone for managed-keys.
733
 
         */
734
 
        obj = NULL;
735
 
        (void)ns_config_get(maps, "managed-keys-directory", &obj);
736
 
        directory = obj != NULL ? cfg_obj_asstring(obj) : NULL;
737
 
        CHECK(add_keydata_zone(view, directory, ns_g_mctx));
738
 
 
739
 
  cleanup:
740
 
        return (result);
741
 
}
742
 
 
743
 
static isc_result_t
744
 
mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
745
 
        const cfg_listelt_t *element;
746
 
        const cfg_obj_t *obj;
747
 
        const char *str;
748
 
        dns_fixedname_t fixed;
749
 
        dns_name_t *name;
750
 
        isc_boolean_t value;
751
 
        isc_result_t result;
752
 
        isc_buffer_t b;
753
 
 
754
 
        dns_fixedname_init(&fixed);
755
 
        name = dns_fixedname_name(&fixed);
756
 
        for (element = cfg_list_first(mbs);
757
 
             element != NULL;
758
 
             element = cfg_list_next(element))
759
 
        {
760
 
                obj = cfg_listelt_value(element);
761
 
                str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
762
 
                isc_buffer_init(&b, str, strlen(str));
763
 
                isc_buffer_add(&b, strlen(str));
764
 
                CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
765
 
                value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
766
 
                CHECK(dns_resolver_setmustbesecure(resolver, name, value));
767
 
        }
768
 
 
769
 
        result = ISC_R_SUCCESS;
770
 
 
771
 
 cleanup:
772
 
        return (result);
773
 
}
774
 
 
775
 
/*%
776
 
 * Get a dispatch appropriate for the resolver of a given view.
777
 
 */
778
 
static isc_result_t
779
 
get_view_querysource_dispatch(const cfg_obj_t **maps,
780
 
                              int af, dns_dispatch_t **dispatchp,
781
 
                              isc_boolean_t is_firstview)
782
 
{
783
 
        isc_result_t result;
784
 
        dns_dispatch_t *disp;
785
 
        isc_sockaddr_t sa;
786
 
        unsigned int attrs, attrmask;
787
 
        const cfg_obj_t *obj = NULL;
788
 
        unsigned int maxdispatchbuffers;
789
 
 
790
 
        /*
791
 
         * Make compiler happy.
792
 
         */
793
 
        result = ISC_R_FAILURE;
794
 
 
795
 
        switch (af) {
796
 
        case AF_INET:
797
 
                result = ns_config_get(maps, "query-source", &obj);
798
 
                INSIST(result == ISC_R_SUCCESS);
799
 
                break;
800
 
        case AF_INET6:
801
 
                result = ns_config_get(maps, "query-source-v6", &obj);
802
 
                INSIST(result == ISC_R_SUCCESS);
803
 
                break;
804
 
        default:
805
 
                INSIST(0);
806
 
        }
807
 
 
808
 
        sa = *(cfg_obj_assockaddr(obj));
809
 
        INSIST(isc_sockaddr_pf(&sa) == af);
810
 
 
811
 
        /*
812
 
         * If we don't support this address family, we're done!
813
 
         */
814
 
        switch (af) {
815
 
        case AF_INET:
816
 
                result = isc_net_probeipv4();
817
 
                break;
818
 
        case AF_INET6:
819
 
                result = isc_net_probeipv6();
820
 
                break;
821
 
        default:
822
 
                INSIST(0);
823
 
        }
824
 
        if (result != ISC_R_SUCCESS)
825
 
                return (ISC_R_SUCCESS);
826
 
 
827
 
        /*
828
 
         * Try to find a dispatcher that we can share.
829
 
         */
830
 
        attrs = 0;
831
 
        attrs |= DNS_DISPATCHATTR_UDP;
832
 
        switch (af) {
833
 
        case AF_INET:
834
 
                attrs |= DNS_DISPATCHATTR_IPV4;
835
 
                break;
836
 
        case AF_INET6:
837
 
                attrs |= DNS_DISPATCHATTR_IPV6;
838
 
                break;
839
 
        }
840
 
        if (isc_sockaddr_getport(&sa) == 0) {
841
 
                attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
842
 
                maxdispatchbuffers = 4096;
843
 
        } else {
844
 
                INSIST(obj != NULL);
845
 
                if (is_firstview) {
846
 
                        cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
847
 
                                    "using specific query-source port "
848
 
                                    "suppresses port randomization and can be "
849
 
                                    "insecure.");
850
 
                }
851
 
                maxdispatchbuffers = 1000;
852
 
        }
853
 
 
854
 
        attrmask = 0;
855
 
        attrmask |= DNS_DISPATCHATTR_UDP;
856
 
        attrmask |= DNS_DISPATCHATTR_TCP;
857
 
        attrmask |= DNS_DISPATCHATTR_IPV4;
858
 
        attrmask |= DNS_DISPATCHATTR_IPV6;
859
 
 
860
 
        disp = NULL;
861
 
        result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
862
 
                                     ns_g_taskmgr, &sa, 4096,
863
 
                                     maxdispatchbuffers, 32768, 16411, 16433,
864
 
                                     attrs, attrmask, &disp);
865
 
        if (result != ISC_R_SUCCESS) {
866
 
                isc_sockaddr_t any;
867
 
                char buf[ISC_SOCKADDR_FORMATSIZE];
868
 
 
869
 
                switch (af) {
870
 
                case AF_INET:
871
 
                        isc_sockaddr_any(&any);
872
 
                        break;
873
 
                case AF_INET6:
874
 
                        isc_sockaddr_any6(&any);
875
 
                        break;
876
 
                }
877
 
                if (isc_sockaddr_equal(&sa, &any))
878
 
                        return (ISC_R_SUCCESS);
879
 
                isc_sockaddr_format(&sa, buf, sizeof(buf));
880
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
881
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
882
 
                              "could not get query source dispatcher (%s)",
883
 
                              buf);
884
 
                return (result);
885
 
        }
886
 
 
887
 
        *dispatchp = disp;
888
 
 
889
 
        return (ISC_R_SUCCESS);
890
 
}
891
 
 
892
 
static isc_result_t
893
 
configure_order(dns_order_t *order, const cfg_obj_t *ent) {
894
 
        dns_rdataclass_t rdclass;
895
 
        dns_rdatatype_t rdtype;
896
 
        const cfg_obj_t *obj;
897
 
        dns_fixedname_t fixed;
898
 
        unsigned int mode = 0;
899
 
        const char *str;
900
 
        isc_buffer_t b;
901
 
        isc_result_t result;
902
 
        isc_boolean_t addroot;
903
 
 
904
 
        result = ns_config_getclass(cfg_tuple_get(ent, "class"),
905
 
                                    dns_rdataclass_any, &rdclass);
906
 
        if (result != ISC_R_SUCCESS)
907
 
                return (result);
908
 
 
909
 
        result = ns_config_gettype(cfg_tuple_get(ent, "type"),
910
 
                                   dns_rdatatype_any, &rdtype);
911
 
        if (result != ISC_R_SUCCESS)
912
 
                return (result);
913
 
 
914
 
        obj = cfg_tuple_get(ent, "name");
915
 
        if (cfg_obj_isstring(obj))
916
 
                str = cfg_obj_asstring(obj);
917
 
        else
918
 
                str = "*";
919
 
        addroot = ISC_TF(strcmp(str, "*") == 0);
920
 
        isc_buffer_init(&b, str, strlen(str));
921
 
        isc_buffer_add(&b, strlen(str));
922
 
        dns_fixedname_init(&fixed);
923
 
        result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
924
 
                                   dns_rootname, 0, NULL);
925
 
        if (result != ISC_R_SUCCESS)
926
 
                return (result);
927
 
 
928
 
        obj = cfg_tuple_get(ent, "ordering");
929
 
        INSIST(cfg_obj_isstring(obj));
930
 
        str = cfg_obj_asstring(obj);
931
 
        if (!strcasecmp(str, "fixed"))
932
 
                mode = DNS_RDATASETATTR_FIXEDORDER;
933
 
        else if (!strcasecmp(str, "random"))
934
 
                mode = DNS_RDATASETATTR_RANDOMIZE;
935
 
        else if (!strcasecmp(str, "cyclic"))
936
 
                mode = 0;
937
 
        else
938
 
                INSIST(0);
939
 
 
940
 
        /*
941
 
         * "*" should match everything including the root (BIND 8 compat).
942
 
         * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
943
 
         * explicit entry for "." when the name is "*".
944
 
         */
945
 
        if (addroot) {
946
 
                result = dns_order_add(order, dns_rootname,
947
 
                                       rdtype, rdclass, mode);
948
 
                if (result != ISC_R_SUCCESS)
949
 
                        return (result);
950
 
        }
951
 
 
952
 
        return (dns_order_add(order, dns_fixedname_name(&fixed),
953
 
                              rdtype, rdclass, mode));
954
 
}
955
 
 
956
 
static isc_result_t
957
 
configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
958
 
        isc_netaddr_t na;
959
 
        dns_peer_t *peer;
960
 
        const cfg_obj_t *obj;
961
 
        const char *str;
962
 
        isc_result_t result;
963
 
        unsigned int prefixlen;
964
 
 
965
 
        cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
966
 
 
967
 
        peer = NULL;
968
 
        result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
969
 
        if (result != ISC_R_SUCCESS)
970
 
                return (result);
971
 
 
972
 
        obj = NULL;
973
 
        (void)cfg_map_get(cpeer, "bogus", &obj);
974
 
        if (obj != NULL)
975
 
                CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
976
 
 
977
 
        obj = NULL;
978
 
        (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
979
 
        if (obj != NULL)
980
 
                CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
981
 
 
982
 
        obj = NULL;
983
 
        (void)cfg_map_get(cpeer, "request-ixfr", &obj);
984
 
        if (obj != NULL)
985
 
                CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
986
 
 
987
 
        obj = NULL;
988
 
        (void)cfg_map_get(cpeer, "request-nsid", &obj);
989
 
        if (obj != NULL)
990
 
                CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
991
 
 
992
 
        obj = NULL;
993
 
        (void)cfg_map_get(cpeer, "edns", &obj);
994
 
        if (obj != NULL)
995
 
                CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
996
 
 
997
 
        obj = NULL;
998
 
        (void)cfg_map_get(cpeer, "edns-udp-size", &obj);
999
 
        if (obj != NULL) {
1000
 
                isc_uint32_t udpsize = cfg_obj_asuint32(obj);
1001
 
                if (udpsize < 512)
1002
 
                        udpsize = 512;
1003
 
                if (udpsize > 4096)
1004
 
                        udpsize = 4096;
1005
 
                CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize));
1006
 
        }
1007
 
 
1008
 
        obj = NULL;
1009
 
        (void)cfg_map_get(cpeer, "max-udp-size", &obj);
1010
 
        if (obj != NULL) {
1011
 
                isc_uint32_t udpsize = cfg_obj_asuint32(obj);
1012
 
                if (udpsize < 512)
1013
 
                        udpsize = 512;
1014
 
                if (udpsize > 4096)
1015
 
                        udpsize = 4096;
1016
 
                CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize));
1017
 
        }
1018
 
 
1019
 
        obj = NULL;
1020
 
        (void)cfg_map_get(cpeer, "transfers", &obj);
1021
 
        if (obj != NULL)
1022
 
                CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
1023
 
 
1024
 
        obj = NULL;
1025
 
        (void)cfg_map_get(cpeer, "transfer-format", &obj);
1026
 
        if (obj != NULL) {
1027
 
                str = cfg_obj_asstring(obj);
1028
 
                if (strcasecmp(str, "many-answers") == 0)
1029
 
                        CHECK(dns_peer_settransferformat(peer,
1030
 
                                                         dns_many_answers));
1031
 
                else if (strcasecmp(str, "one-answer") == 0)
1032
 
                        CHECK(dns_peer_settransferformat(peer,
1033
 
                                                         dns_one_answer));
1034
 
                else
1035
 
                        INSIST(0);
1036
 
        }
1037
 
 
1038
 
        obj = NULL;
1039
 
        (void)cfg_map_get(cpeer, "keys", &obj);
1040
 
        if (obj != NULL) {
1041
 
                result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
1042
 
                if (result != ISC_R_SUCCESS)
1043
 
                        goto cleanup;
1044
 
        }
1045
 
 
1046
 
        obj = NULL;
1047
 
        if (na.family == AF_INET)
1048
 
                (void)cfg_map_get(cpeer, "transfer-source", &obj);
1049
 
        else
1050
 
                (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
1051
 
        if (obj != NULL) {
1052
 
                result = dns_peer_settransfersource(peer,
1053
 
                                                    cfg_obj_assockaddr(obj));
1054
 
                if (result != ISC_R_SUCCESS)
1055
 
                        goto cleanup;
1056
 
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1057
 
        }
1058
 
 
1059
 
        obj = NULL;
1060
 
        if (na.family == AF_INET)
1061
 
                (void)cfg_map_get(cpeer, "notify-source", &obj);
1062
 
        else
1063
 
                (void)cfg_map_get(cpeer, "notify-source-v6", &obj);
1064
 
        if (obj != NULL) {
1065
 
                result = dns_peer_setnotifysource(peer,
1066
 
                                                  cfg_obj_assockaddr(obj));
1067
 
                if (result != ISC_R_SUCCESS)
1068
 
                        goto cleanup;
1069
 
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1070
 
        }
1071
 
 
1072
 
        obj = NULL;
1073
 
        if (na.family == AF_INET)
1074
 
                (void)cfg_map_get(cpeer, "query-source", &obj);
1075
 
        else
1076
 
                (void)cfg_map_get(cpeer, "query-source-v6", &obj);
1077
 
        if (obj != NULL) {
1078
 
                result = dns_peer_setquerysource(peer,
1079
 
                                                 cfg_obj_assockaddr(obj));
1080
 
                if (result != ISC_R_SUCCESS)
1081
 
                        goto cleanup;
1082
 
                ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1083
 
        }
1084
 
 
1085
 
        *peerp = peer;
1086
 
        return (ISC_R_SUCCESS);
1087
 
 
1088
 
 cleanup:
1089
 
        dns_peer_detach(&peer);
1090
 
        return (result);
1091
 
}
1092
 
 
1093
 
static isc_result_t
1094
 
disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
1095
 
        isc_result_t result;
1096
 
        const cfg_obj_t *algorithms;
1097
 
        const cfg_listelt_t *element;
1098
 
        const char *str;
1099
 
        dns_fixedname_t fixed;
1100
 
        dns_name_t *name;
1101
 
        isc_buffer_t b;
1102
 
 
1103
 
        dns_fixedname_init(&fixed);
1104
 
        name = dns_fixedname_name(&fixed);
1105
 
        str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
1106
 
        isc_buffer_init(&b, str, strlen(str));
1107
 
        isc_buffer_add(&b, strlen(str));
1108
 
        CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
1109
 
 
1110
 
        algorithms = cfg_tuple_get(disabled, "algorithms");
1111
 
        for (element = cfg_list_first(algorithms);
1112
 
             element != NULL;
1113
 
             element = cfg_list_next(element))
1114
 
        {
1115
 
                isc_textregion_t r;
1116
 
                dns_secalg_t alg;
1117
 
 
1118
 
                DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
1119
 
                r.length = strlen(r.base);
1120
 
 
1121
 
                result = dns_secalg_fromtext(&alg, &r);
1122
 
                if (result != ISC_R_SUCCESS) {
1123
 
                        isc_uint8_t ui;
1124
 
                        result = isc_parse_uint8(&ui, r.base, 10);
1125
 
                        alg = ui;
1126
 
                }
1127
 
                if (result != ISC_R_SUCCESS) {
1128
 
                        cfg_obj_log(cfg_listelt_value(element),
1129
 
                                    ns_g_lctx, ISC_LOG_ERROR,
1130
 
                                    "invalid algorithm");
1131
 
                        CHECK(result);
1132
 
                }
1133
 
                CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
1134
 
        }
1135
 
 cleanup:
1136
 
        return (result);
1137
 
}
1138
 
 
1139
 
static isc_boolean_t
1140
 
on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
1141
 
        const cfg_listelt_t *element;
1142
 
        dns_fixedname_t fixed;
1143
 
        dns_name_t *name;
1144
 
        isc_result_t result;
1145
 
        const cfg_obj_t *value;
1146
 
        const char *str;
1147
 
        isc_buffer_t b;
1148
 
 
1149
 
        dns_fixedname_init(&fixed);
1150
 
        name = dns_fixedname_name(&fixed);
1151
 
 
1152
 
        for (element = cfg_list_first(disablelist);
1153
 
             element != NULL;
1154
 
             element = cfg_list_next(element))
1155
 
        {
1156
 
                value = cfg_listelt_value(element);
1157
 
                str = cfg_obj_asstring(value);
1158
 
                isc_buffer_init(&b, str, strlen(str));
1159
 
                isc_buffer_add(&b, strlen(str));
1160
 
                result = dns_name_fromtext(name, &b, dns_rootname,
1161
 
                                           0, NULL);
1162
 
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
1163
 
                if (dns_name_equal(name, zonename))
1164
 
                        return (ISC_TRUE);
1165
 
        }
1166
 
        return (ISC_FALSE);
1167
 
}
1168
 
 
1169
 
static void
1170
 
check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv,
1171
 
             isc_mem_t *mctx)
1172
 
{
1173
 
        char **argv = NULL;
1174
 
        unsigned int i;
1175
 
        isc_result_t result;
1176
 
 
1177
 
        result = dns_zone_getdbtype(*zonep, &argv, mctx);
1178
 
        if (result != ISC_R_SUCCESS) {
1179
 
                dns_zone_detach(zonep);
1180
 
                return;
1181
 
        }
1182
 
 
1183
 
        /*
1184
 
         * Check that all the arguments match.
1185
 
         */
1186
 
        for (i = 0; i < dbtypec; i++)
1187
 
                if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) {
1188
 
                        dns_zone_detach(zonep);
1189
 
                        break;
1190
 
                }
1191
 
 
1192
 
        /*
1193
 
         * Check that there are not extra arguments.
1194
 
         */
1195
 
        if (i == dbtypec && argv[i] != NULL)
1196
 
                dns_zone_detach(zonep);
1197
 
        isc_mem_free(mctx, argv);
1198
 
}
1199
 
 
1200
 
static isc_result_t
1201
 
setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
1202
 
        isc_result_t result;
1203
 
        isc_stats_t *zoneqrystats;
1204
 
 
1205
 
        zoneqrystats = NULL;
1206
 
        if (on) {
1207
 
                result = isc_stats_create(mctx, &zoneqrystats,
1208
 
                                          dns_nsstatscounter_max);
1209
 
                if (result != ISC_R_SUCCESS)
1210
 
                        return (result);
1211
 
        }
1212
 
        dns_zone_setrequeststats(zone, zoneqrystats);
1213
 
        if (zoneqrystats != NULL)
1214
 
                isc_stats_detach(&zoneqrystats);
1215
 
 
1216
 
        return (ISC_R_SUCCESS);
1217
 
}
1218
 
 
1219
 
static ns_cache_t *
1220
 
cachelist_find(ns_cachelist_t *cachelist, const char *cachename) {
1221
 
        ns_cache_t *nsc;
1222
 
 
1223
 
        for (nsc = ISC_LIST_HEAD(*cachelist);
1224
 
             nsc != NULL;
1225
 
             nsc = ISC_LIST_NEXT(nsc, link)) {
1226
 
                if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0)
1227
 
                        return (nsc);
1228
 
        }
1229
 
 
1230
 
        return (NULL);
1231
 
}
1232
 
 
1233
 
static isc_boolean_t
1234
 
cache_reusable(dns_view_t *originview, dns_view_t *view,
1235
 
               isc_boolean_t new_zero_no_soattl)
1236
 
{
1237
 
        if (originview->checknames != view->checknames ||
1238
 
            dns_resolver_getzeronosoattl(originview->resolver) !=
1239
 
            new_zero_no_soattl ||
1240
 
            originview->acceptexpired != view->acceptexpired ||
1241
 
            originview->enablevalidation != view->enablevalidation ||
1242
 
            originview->maxcachettl != view->maxcachettl ||
1243
 
            originview->maxncachettl != view->maxncachettl) {
1244
 
                return (ISC_FALSE);
1245
 
        }
1246
 
 
1247
 
        return (ISC_TRUE);
1248
 
}
1249
 
 
1250
 
static isc_boolean_t
1251
 
cache_sharable(dns_view_t *originview, dns_view_t *view,
1252
 
               isc_boolean_t new_zero_no_soattl,
1253
 
               unsigned int new_cleaning_interval,
1254
 
               isc_uint32_t new_max_cache_size)
1255
 
{
1256
 
        /*
1257
 
         * If the cache cannot even reused for the same view, it cannot be
1258
 
         * shared with other views.
1259
 
         */
1260
 
        if (!cache_reusable(originview, view, new_zero_no_soattl))
1261
 
                return (ISC_FALSE);
1262
 
 
1263
 
        /*
1264
 
         * Check other cache related parameters that must be consistent among
1265
 
         * the sharing views.
1266
 
         */
1267
 
        if (dns_cache_getcleaninginterval(originview->cache) !=
1268
 
            new_cleaning_interval ||
1269
 
            dns_cache_getcachesize(originview->cache) != new_max_cache_size) {
1270
 
                return (ISC_FALSE);
1271
 
        }
1272
 
 
1273
 
        return (ISC_TRUE);
1274
 
}
1275
 
 
1276
 
/*
1277
 
 * Configure 'view' according to 'vconfig', taking defaults from 'config'
1278
 
 * where values are missing in 'vconfig'.
1279
 
 *
1280
 
 * When configuring the default view, 'vconfig' will be NULL and the
1281
 
 * global defaults in 'config' used exclusively.
1282
 
 */
1283
 
static isc_result_t
1284
 
configure_view(dns_view_t *view, const cfg_obj_t *config,
1285
 
               const cfg_obj_t *vconfig, ns_cachelist_t *cachelist,
1286
 
               const cfg_obj_t *bindkeys, isc_mem_t *mctx,
1287
 
               cfg_aclconfctx_t *actx, isc_boolean_t need_hints)
1288
 
{
1289
 
        const cfg_obj_t *maps[4];
1290
 
        const cfg_obj_t *cfgmaps[3];
1291
 
        const cfg_obj_t *optionmaps[3];
1292
 
        const cfg_obj_t *options = NULL;
1293
 
        const cfg_obj_t *voptions = NULL;
1294
 
        const cfg_obj_t *forwardtype;
1295
 
        const cfg_obj_t *forwarders;
1296
 
        const cfg_obj_t *alternates;
1297
 
        const cfg_obj_t *zonelist;
1298
 
#ifdef DLZ
1299
 
        const cfg_obj_t *dlz;
1300
 
        unsigned int dlzargc;
1301
 
        char **dlzargv;
1302
 
#endif
1303
 
        const cfg_obj_t *disabled;
1304
 
        const cfg_obj_t *obj;
1305
 
        const cfg_listelt_t *element;
1306
 
        in_port_t port;
1307
 
        dns_cache_t *cache = NULL;
1308
 
        isc_result_t result;
1309
 
        isc_uint32_t max_adb_size;
1310
 
        unsigned int cleaning_interval;
1311
 
        isc_uint32_t max_cache_size;
1312
 
        isc_uint32_t max_acache_size;
1313
 
        isc_uint32_t lame_ttl;
1314
 
        dns_tsig_keyring_t *ring = NULL;
1315
 
        dns_view_t *pview = NULL;       /* Production view */
1316
 
        isc_mem_t *cmctx;
1317
 
        dns_dispatch_t *dispatch4 = NULL;
1318
 
        dns_dispatch_t *dispatch6 = NULL;
1319
 
        isc_boolean_t reused_cache = ISC_FALSE;
1320
 
        isc_boolean_t shared_cache = ISC_FALSE;
1321
 
        int i = 0, j = 0, k = 0;
1322
 
        const char *str;
1323
 
        const char *cachename = NULL;
1324
 
        dns_order_t *order = NULL;
1325
 
        isc_uint32_t udpsize;
1326
 
        unsigned int resopts = 0;
1327
 
        dns_zone_t *zone = NULL;
1328
 
        isc_uint32_t max_clients_per_query;
1329
 
        const char *sep = ": view ";
1330
 
        const char *viewname = view->name;
1331
 
        const char *forview = " for view ";
1332
 
        isc_boolean_t rfc1918;
1333
 
        isc_boolean_t empty_zones_enable;
1334
 
        const cfg_obj_t *disablelist = NULL;
1335
 
        isc_stats_t *resstats = NULL;
1336
 
        dns_stats_t *resquerystats = NULL;
1337
 
        isc_boolean_t auto_dlv = ISC_FALSE;
1338
 
        ns_cache_t *nsc;
1339
 
        isc_boolean_t zero_no_soattl;
1340
 
 
1341
 
        REQUIRE(DNS_VIEW_VALID(view));
1342
 
 
1343
 
        cmctx = NULL;
1344
 
 
1345
 
        if (config != NULL)
1346
 
                (void)cfg_map_get(config, "options", &options);
1347
 
 
1348
 
        /*
1349
 
         * maps: view options, options, defaults
1350
 
         * cfgmaps: view options, config
1351
 
         * optionmaps: view options, options
1352
 
         */
1353
 
        if (vconfig != NULL) {
1354
 
                voptions = cfg_tuple_get(vconfig, "options");
1355
 
                maps[i++] = voptions;
1356
 
                optionmaps[j++] = voptions;
1357
 
                cfgmaps[k++] = voptions;
1358
 
        }
1359
 
        if (options != NULL) {
1360
 
                maps[i++] = options;
1361
 
                optionmaps[j++] = options;
1362
 
        }
1363
 
 
1364
 
        maps[i++] = ns_g_defaults;
1365
 
        maps[i] = NULL;
1366
 
        optionmaps[j] = NULL;
1367
 
        if (config != NULL)
1368
 
                cfgmaps[k++] = config;
1369
 
        cfgmaps[k] = NULL;
1370
 
 
1371
 
        if (!strcmp(viewname, "_default")) {
1372
 
                sep = "";
1373
 
                viewname = "";
1374
 
                forview = "";
1375
 
        }
1376
 
 
1377
 
        /*
1378
 
         * Set the view's port number for outgoing queries.
1379
 
         */
1380
 
        CHECKM(ns_config_getport(config, &port), "port");
1381
 
        dns_view_setdstport(view, port);
1382
 
 
1383
 
        /*
1384
 
         * Create additional cache for this view and zones under the view
1385
 
         * if explicitly enabled.
1386
 
         * XXX950 default to on.
1387
 
         */
1388
 
        obj = NULL;
1389
 
        (void)ns_config_get(maps, "acache-enable", &obj);
1390
 
        if (obj != NULL && cfg_obj_asboolean(obj)) {
1391
 
                cmctx = NULL;
1392
 
                CHECK(isc_mem_create(0, 0, &cmctx));
1393
 
                CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
1394
 
                                        ns_g_timermgr));
1395
 
                isc_mem_setname(cmctx, "acache", NULL);
1396
 
                isc_mem_detach(&cmctx);
1397
 
        }
1398
 
        if (view->acache != NULL) {
1399
 
                obj = NULL;
1400
 
                result = ns_config_get(maps, "acache-cleaning-interval", &obj);
1401
 
                INSIST(result == ISC_R_SUCCESS);
1402
 
                dns_acache_setcleaninginterval(view->acache,
1403
 
                                               cfg_obj_asuint32(obj) * 60);
1404
 
 
1405
 
                obj = NULL;
1406
 
                result = ns_config_get(maps, "max-acache-size", &obj);
1407
 
                INSIST(result == ISC_R_SUCCESS);
1408
 
                if (cfg_obj_isstring(obj)) {
1409
 
                        str = cfg_obj_asstring(obj);
1410
 
                        INSIST(strcasecmp(str, "unlimited") == 0);
1411
 
                        max_acache_size = ISC_UINT32_MAX;
1412
 
                } else {
1413
 
                        isc_resourcevalue_t value;
1414
 
 
1415
 
                        value = cfg_obj_asuint64(obj);
1416
 
                        if (value > ISC_UINT32_MAX) {
1417
 
                                cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1418
 
                                            "'max-acache-size "
1419
 
                                            "%" ISC_PRINT_QUADFORMAT
1420
 
                                            "d' is too large",
1421
 
                                            value);
1422
 
                                result = ISC_R_RANGE;
1423
 
                                goto cleanup;
1424
 
                        }
1425
 
                        max_acache_size = (isc_uint32_t)value;
1426
 
                }
1427
 
                dns_acache_setcachesize(view->acache, max_acache_size);
1428
 
        }
1429
 
 
1430
 
        /*
1431
 
         * Configure the zones.
1432
 
         */
1433
 
        zonelist = NULL;
1434
 
        if (voptions != NULL)
1435
 
                (void)cfg_map_get(voptions, "zone", &zonelist);
1436
 
        else
1437
 
                (void)cfg_map_get(config, "zone", &zonelist);
1438
 
        for (element = cfg_list_first(zonelist);
1439
 
             element != NULL;
1440
 
             element = cfg_list_next(element))
1441
 
        {
1442
 
                const cfg_obj_t *zconfig = cfg_listelt_value(element);
1443
 
                CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
1444
 
                                     actx));
1445
 
        }
1446
 
 
1447
 
#ifdef DLZ
1448
 
        /*
1449
 
         * Create Dynamically Loadable Zone driver.
1450
 
         */
1451
 
        dlz = NULL;
1452
 
        if (voptions != NULL)
1453
 
                (void)cfg_map_get(voptions, "dlz", &dlz);
1454
 
        else
1455
 
                (void)cfg_map_get(config, "dlz", &dlz);
1456
 
 
1457
 
        obj = NULL;
1458
 
        if (dlz != NULL) {
1459
 
                (void)cfg_map_get(cfg_tuple_get(dlz, "options"),
1460
 
                                  "database", &obj);
1461
 
                if (obj != NULL) {
1462
 
                        char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
1463
 
                        if (s == NULL) {
1464
 
                                result = ISC_R_NOMEMORY;
1465
 
                                goto cleanup;
1466
 
                        }
1467
 
 
1468
 
                        result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
1469
 
                        if (result != ISC_R_SUCCESS) {
1470
 
                                isc_mem_free(mctx, s);
1471
 
                                goto cleanup;
1472
 
                        }
1473
 
 
1474
 
                        obj = cfg_tuple_get(dlz, "name");
1475
 
                        result = dns_dlzcreate(mctx, cfg_obj_asstring(obj),
1476
 
                                               dlzargv[0], dlzargc, dlzargv,
1477
 
                                               &view->dlzdatabase);
1478
 
                        isc_mem_free(mctx, s);
1479
 
                        isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
1480
 
                        if (result != ISC_R_SUCCESS)
1481
 
                                goto cleanup;
1482
 
                }
1483
 
        }
1484
 
#endif
1485
 
 
1486
 
        /*
1487
 
         * Obtain configuration parameters that affect the decision of whether
1488
 
         * we can reuse/share an existing cache.
1489
 
         */
1490
 
        obj = NULL;
1491
 
        result = ns_config_get(maps, "cleaning-interval", &obj);
1492
 
        INSIST(result == ISC_R_SUCCESS);
1493
 
        cleaning_interval = cfg_obj_asuint32(obj) * 60;
1494
 
 
1495
 
        obj = NULL;
1496
 
        result = ns_config_get(maps, "max-cache-size", &obj);
1497
 
        INSIST(result == ISC_R_SUCCESS);
1498
 
        if (cfg_obj_isstring(obj)) {
1499
 
                str = cfg_obj_asstring(obj);
1500
 
                INSIST(strcasecmp(str, "unlimited") == 0);
1501
 
                max_cache_size = ISC_UINT32_MAX;
1502
 
        } else {
1503
 
                isc_resourcevalue_t value;
1504
 
                value = cfg_obj_asuint64(obj);
1505
 
                if (value > ISC_UINT32_MAX) {
1506
 
                        cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
1507
 
                                    "'max-cache-size "
1508
 
                                    "%" ISC_PRINT_QUADFORMAT "d' is too large",
1509
 
                                    value);
1510
 
                        result = ISC_R_RANGE;
1511
 
                        goto cleanup;
1512
 
                }
1513
 
                max_cache_size = (isc_uint32_t)value;
1514
 
        }
1515
 
 
1516
 
        /* Check-names. */
1517
 
        obj = NULL;
1518
 
        result = ns_checknames_get(maps, "response", &obj);
1519
 
        INSIST(result == ISC_R_SUCCESS);
1520
 
 
1521
 
        str = cfg_obj_asstring(obj);
1522
 
        if (strcasecmp(str, "fail") == 0) {
1523
 
                resopts |= DNS_RESOLVER_CHECKNAMES |
1524
 
                        DNS_RESOLVER_CHECKNAMESFAIL;
1525
 
                view->checknames = ISC_TRUE;
1526
 
        } else if (strcasecmp(str, "warn") == 0) {
1527
 
                resopts |= DNS_RESOLVER_CHECKNAMES;
1528
 
                view->checknames = ISC_FALSE;
1529
 
        } else if (strcasecmp(str, "ignore") == 0) {
1530
 
                view->checknames = ISC_FALSE;
1531
 
        } else
1532
 
                INSIST(0);
1533
 
 
1534
 
        obj = NULL;
1535
 
        result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
1536
 
        INSIST(result == ISC_R_SUCCESS);
1537
 
        zero_no_soattl = cfg_obj_asboolean(obj);
1538
 
 
1539
 
        obj = NULL;
1540
 
        result = ns_config_get(maps, "dnssec-accept-expired", &obj);
1541
 
        INSIST(result == ISC_R_SUCCESS);
1542
 
        view->acceptexpired = cfg_obj_asboolean(obj);
1543
 
 
1544
 
        obj = NULL;
1545
 
        result = ns_config_get(maps, "dnssec-validation", &obj);
1546
 
        INSIST(result == ISC_R_SUCCESS);
1547
 
        view->enablevalidation = cfg_obj_asboolean(obj);
1548
 
 
1549
 
        obj = NULL;
1550
 
        result = ns_config_get(maps, "max-cache-ttl", &obj);
1551
 
        INSIST(result == ISC_R_SUCCESS);
1552
 
        view->maxcachettl = cfg_obj_asuint32(obj);
1553
 
 
1554
 
        obj = NULL;
1555
 
        result = ns_config_get(maps, "max-ncache-ttl", &obj);
1556
 
        INSIST(result == ISC_R_SUCCESS);
1557
 
        view->maxncachettl = cfg_obj_asuint32(obj);
1558
 
        if (view->maxncachettl > 7 * 24 * 3600)
1559
 
                view->maxncachettl = 7 * 24 * 3600;
1560
 
 
1561
 
        /*
1562
 
         * Configure the view's cache.
1563
 
         *
1564
 
         * First, check to see if there are any attach-cache options.  If yes,
1565
 
         * attempt to lookup an existing cache at attach it to the view.  If
1566
 
         * there is not one, then try to reuse an existing cache if possible;
1567
 
         * otherwise create a new cache.
1568
 
         *
1569
 
         * Note that the ADB is not preserved or shared in either case.
1570
 
         *
1571
 
         * When a matching view is found, the associated statistics are also
1572
 
         * retrieved and reused.
1573
 
         *
1574
 
         * XXX Determining when it is safe to reuse or share a cache is tricky.
1575
 
         * When the view's configuration changes, the cached data may become
1576
 
         * invalid because it reflects our old view of the world.  We check
1577
 
         * some of the configuration parameters that could invalidate the cache
1578
 
         * or otherwise make it unsharable, but there are other configuration
1579
 
         * options that should be checked.  For example, if a view uses a
1580
 
         * forwarder, changes in the forwarder configuration may invalidate
1581
 
         * the cache.  At the moment, it's the administrator's responsibility to
1582
 
         * ensure these configuration options don't invalidate reusing/sharing.
1583
 
         */
1584
 
        obj = NULL;
1585
 
        result = ns_config_get(maps, "attach-cache", &obj);
1586
 
        if (result == ISC_R_SUCCESS)
1587
 
                cachename = cfg_obj_asstring(obj);
1588
 
        else
1589
 
                cachename = view->name;
1590
 
        cache = NULL;
1591
 
        nsc = cachelist_find(cachelist, cachename);
1592
 
        if (nsc != NULL) {
1593
 
                if (!cache_sharable(nsc->primaryview, view, zero_no_soattl,
1594
 
                                    cleaning_interval, max_cache_size)) {
1595
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1596
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
1597
 
                                      "views %s and %s can't share the cache "
1598
 
                                      "due to configuration parameter mismatch",
1599
 
                                      nsc->primaryview->name, view->name);
1600
 
                        result = ISC_R_FAILURE;
1601
 
                        goto cleanup;
1602
 
                }
1603
 
                dns_cache_attach(nsc->cache, &cache);
1604
 
                shared_cache = ISC_TRUE;
1605
 
        } else {
1606
 
                if (strcmp(cachename, view->name) == 0) {
1607
 
                        result = dns_viewlist_find(&ns_g_server->viewlist,
1608
 
                                                   cachename, view->rdclass,
1609
 
                                                   &pview);
1610
 
                        if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
1611
 
                                goto cleanup;
1612
 
                        if (pview != NULL) {
1613
 
                                if (!cache_reusable(pview, view,
1614
 
                                                    zero_no_soattl)) {
1615
 
                                        isc_log_write(ns_g_lctx,
1616
 
                                                      NS_LOGCATEGORY_GENERAL,
1617
 
                                                      NS_LOGMODULE_SERVER,
1618
 
                                                      ISC_LOG_DEBUG(1),
1619
 
                                                      "cache cannot be reused "
1620
 
                                                      "for view %s due to "
1621
 
                                                      "configuration parameter "
1622
 
                                                      "mismatch", view->name);
1623
 
                                } else {
1624
 
                                        INSIST(pview->cache != NULL);
1625
 
                                        isc_log_write(ns_g_lctx,
1626
 
                                                      NS_LOGCATEGORY_GENERAL,
1627
 
                                                      NS_LOGMODULE_SERVER,
1628
 
                                                      ISC_LOG_DEBUG(3),
1629
 
                                                      "reusing existing cache");
1630
 
                                        reused_cache = ISC_TRUE;
1631
 
                                        dns_cache_attach(pview->cache, &cache);
1632
 
                                }
1633
 
                                dns_view_getresstats(pview, &resstats);
1634
 
                                dns_view_getresquerystats(pview,
1635
 
                                                          &resquerystats);
1636
 
                                dns_view_detach(&pview);
1637
 
                        }
1638
 
                }
1639
 
                if (cache == NULL) {
1640
 
                        /*
1641
 
                         * Create a cache with the desired name.  This normally
1642
 
                         * equals the view name, but may also be a forward
1643
 
                         * reference to a view that share the cache with this
1644
 
                         * view but is not yet configured.  If it is not the
1645
 
                         * view name but not a forward reference either, then it
1646
 
                         * is simply a named cache that is not shared.
1647
 
                         */
1648
 
                        CHECK(isc_mem_create(0, 0, &cmctx));
1649
 
                        isc_mem_setname(cmctx, "cache", NULL);
1650
 
                        CHECK(dns_cache_create2(cmctx, ns_g_taskmgr,
1651
 
                                                ns_g_timermgr, view->rdclass,
1652
 
                                                cachename, "rbt", 0, NULL,
1653
 
                                                &cache));
1654
 
                }
1655
 
                nsc = isc_mem_get(mctx, sizeof(*nsc));
1656
 
                if (nsc == NULL) {
1657
 
                        result = ISC_R_NOMEMORY;
1658
 
                        goto cleanup;
1659
 
                }
1660
 
                nsc->cache = NULL;
1661
 
                dns_cache_attach(cache, &nsc->cache);
1662
 
                nsc->primaryview = view;
1663
 
                nsc->needflush = ISC_FALSE;
1664
 
                nsc->adbsizeadjusted = ISC_FALSE;
1665
 
                ISC_LINK_INIT(nsc, link);
1666
 
                ISC_LIST_APPEND(*cachelist, nsc, link);
1667
 
        }
1668
 
        dns_view_setcache2(view, cache, shared_cache);
1669
 
 
1670
 
        /*
1671
 
         * cache-file cannot be inherited if views are present, but this
1672
 
         * should be caught by the configuration checking stage.
1673
 
         */
1674
 
        obj = NULL;
1675
 
        result = ns_config_get(maps, "cache-file", &obj);
1676
 
        if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
1677
 
                CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
1678
 
                if (!reused_cache && !shared_cache)
1679
 
                        CHECK(dns_cache_load(cache));
1680
 
        }
1681
 
 
1682
 
        dns_cache_setcleaninginterval(cache, cleaning_interval);
1683
 
        dns_cache_setcachesize(cache, max_cache_size);
1684
 
 
1685
 
        dns_cache_detach(&cache);
1686
 
 
1687
 
        /*
1688
 
         * Resolver.
1689
 
         *
1690
 
         * XXXRTH  Hardwired number of tasks.
1691
 
         */
1692
 
        CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
1693
 
                                            ISC_TF(ISC_LIST_PREV(view, link)
1694
 
                                                   == NULL)));
1695
 
        CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
1696
 
                                            ISC_TF(ISC_LIST_PREV(view, link)
1697
 
                                                   == NULL)));
1698
 
        if (dispatch4 == NULL && dispatch6 == NULL) {
1699
 
                UNEXPECTED_ERROR(__FILE__, __LINE__,
1700
 
                                 "unable to obtain neither an IPv4 nor"
1701
 
                                 " an IPv6 dispatch");
1702
 
                result = ISC_R_UNEXPECTED;
1703
 
                goto cleanup;
1704
 
        }
1705
 
        CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
1706
 
                                      ns_g_socketmgr, ns_g_timermgr,
1707
 
                                      resopts, ns_g_dispatchmgr,
1708
 
                                      dispatch4, dispatch6));
1709
 
 
1710
 
        if (resstats == NULL) {
1711
 
                CHECK(isc_stats_create(mctx, &resstats,
1712
 
                                       dns_resstatscounter_max));
1713
 
        }
1714
 
        dns_view_setresstats(view, resstats);
1715
 
        if (resquerystats == NULL)
1716
 
                CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
1717
 
        dns_view_setresquerystats(view, resquerystats);
1718
 
 
1719
 
        /*
1720
 
         * Set the ADB cache size to 1/8th of the max-cache-size or
1721
 
         * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared.
1722
 
         */
1723
 
        max_adb_size = 0;
1724
 
        if (max_cache_size != 0) {
1725
 
                max_adb_size = max_cache_size / 8;
1726
 
                if (max_adb_size == 0)
1727
 
                        max_adb_size = 1;       /* Force minimum. */
1728
 
                if (view != nsc->primaryview &&
1729
 
                    max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) {
1730
 
                        max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE;
1731
 
                        if (!nsc->adbsizeadjusted) {
1732
 
                                dns_adb_setadbsize(nsc->primaryview->adb,
1733
 
                                                   MAX_ADB_SIZE_FOR_CACHESHARE);
1734
 
                                nsc->adbsizeadjusted = ISC_TRUE;
1735
 
                        }
1736
 
                }
1737
 
        }
1738
 
        dns_adb_setadbsize(view->adb, max_adb_size);
1739
 
 
1740
 
        /*
1741
 
         * Set resolver's lame-ttl.
1742
 
         */
1743
 
        obj = NULL;
1744
 
        result = ns_config_get(maps, "lame-ttl", &obj);
1745
 
        INSIST(result == ISC_R_SUCCESS);
1746
 
        lame_ttl = cfg_obj_asuint32(obj);
1747
 
        if (lame_ttl > 1800)
1748
 
                lame_ttl = 1800;
1749
 
        dns_resolver_setlamettl(view->resolver, lame_ttl);
1750
 
 
1751
 
        /* Specify whether to use 0-TTL for negative response for SOA query */
1752
 
        dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl);
1753
 
 
1754
 
        /*
1755
 
         * Set the resolver's EDNS UDP size.
1756
 
         */
1757
 
        obj = NULL;
1758
 
        result = ns_config_get(maps, "edns-udp-size", &obj);
1759
 
        INSIST(result == ISC_R_SUCCESS);
1760
 
        udpsize = cfg_obj_asuint32(obj);
1761
 
        if (udpsize < 512)
1762
 
                udpsize = 512;
1763
 
        if (udpsize > 4096)
1764
 
                udpsize = 4096;
1765
 
        dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
1766
 
 
1767
 
        /*
1768
 
         * Set the maximum UDP response size.
1769
 
         */
1770
 
        obj = NULL;
1771
 
        result = ns_config_get(maps, "max-udp-size", &obj);
1772
 
        INSIST(result == ISC_R_SUCCESS);
1773
 
        udpsize = cfg_obj_asuint32(obj);
1774
 
        if (udpsize < 512)
1775
 
                udpsize = 512;
1776
 
        if (udpsize > 4096)
1777
 
                udpsize = 4096;
1778
 
        view->maxudp = udpsize;
1779
 
 
1780
 
        /*
1781
 
         * Set supported DNSSEC algorithms.
1782
 
         */
1783
 
        dns_resolver_reset_algorithms(view->resolver);
1784
 
        disabled = NULL;
1785
 
        (void)ns_config_get(maps, "disable-algorithms", &disabled);
1786
 
        if (disabled != NULL) {
1787
 
                for (element = cfg_list_first(disabled);
1788
 
                     element != NULL;
1789
 
                     element = cfg_list_next(element))
1790
 
                        CHECK(disable_algorithms(cfg_listelt_value(element),
1791
 
                                                 view->resolver));
1792
 
        }
1793
 
 
1794
 
        /*
1795
 
         * A global or view "forwarders" option, if present,
1796
 
         * creates an entry for "." in the forwarding table.
1797
 
         */
1798
 
        forwardtype = NULL;
1799
 
        forwarders = NULL;
1800
 
        (void)ns_config_get(maps, "forward", &forwardtype);
1801
 
        (void)ns_config_get(maps, "forwarders", &forwarders);
1802
 
        if (forwarders != NULL)
1803
 
                CHECK(configure_forward(config, view, dns_rootname,
1804
 
                                        forwarders, forwardtype));
1805
 
 
1806
 
        /*
1807
 
         * Dual Stack Servers.
1808
 
         */
1809
 
        alternates = NULL;
1810
 
        (void)ns_config_get(maps, "dual-stack-servers", &alternates);
1811
 
        if (alternates != NULL)
1812
 
                CHECK(configure_alternates(config, view, alternates));
1813
 
 
1814
 
        /*
1815
 
         * We have default hints for class IN if we need them.
1816
 
         */
1817
 
        if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
1818
 
                dns_view_sethints(view, ns_g_server->in_roothints);
1819
 
 
1820
 
        /*
1821
 
         * If we still have no hints, this is a non-IN view with no
1822
 
         * "hints zone" configured.  Issue a warning, except if this
1823
 
         * is a root server.  Root servers never need to consult
1824
 
         * their hints, so it's no point requiring users to configure
1825
 
         * them.
1826
 
         */
1827
 
        if (view->hints == NULL) {
1828
 
                dns_zone_t *rootzone = NULL;
1829
 
                (void)dns_view_findzone(view, dns_rootname, &rootzone);
1830
 
                if (rootzone != NULL) {
1831
 
                        dns_zone_detach(&rootzone);
1832
 
                        need_hints = ISC_FALSE;
1833
 
                }
1834
 
                if (need_hints)
1835
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1836
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1837
 
                                      "no root hints for view '%s'",
1838
 
                                      view->name);
1839
 
        }
1840
 
 
1841
 
        /*
1842
 
         * Configure the view's TSIG keys.
1843
 
         */
1844
 
        CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
1845
 
        if (ns_g_server->sessionkey != NULL) {
1846
 
                CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname,
1847
 
                                          ns_g_server->sessionkey));
1848
 
        }
1849
 
        dns_view_setkeyring(view, ring);
1850
 
        ring = NULL;            /* ownership transferred */
1851
 
 
1852
 
        /*
1853
 
         * Configure the view's peer list.
1854
 
         */
1855
 
        {
1856
 
                const cfg_obj_t *peers = NULL;
1857
 
                const cfg_listelt_t *element;
1858
 
                dns_peerlist_t *newpeers = NULL;
1859
 
 
1860
 
                (void)ns_config_get(cfgmaps, "server", &peers);
1861
 
                CHECK(dns_peerlist_new(mctx, &newpeers));
1862
 
                for (element = cfg_list_first(peers);
1863
 
                     element != NULL;
1864
 
                     element = cfg_list_next(element))
1865
 
                {
1866
 
                        const cfg_obj_t *cpeer = cfg_listelt_value(element);
1867
 
                        dns_peer_t *peer;
1868
 
 
1869
 
                        CHECK(configure_peer(cpeer, mctx, &peer));
1870
 
                        dns_peerlist_addpeer(newpeers, peer);
1871
 
                        dns_peer_detach(&peer);
1872
 
                }
1873
 
                dns_peerlist_detach(&view->peers);
1874
 
                view->peers = newpeers; /* Transfer ownership. */
1875
 
        }
1876
 
 
1877
 
        /*
1878
 
         *      Configure the views rrset-order.
1879
 
         */
1880
 
        {
1881
 
                const cfg_obj_t *rrsetorder = NULL;
1882
 
                const cfg_listelt_t *element;
1883
 
 
1884
 
                (void)ns_config_get(maps, "rrset-order", &rrsetorder);
1885
 
                CHECK(dns_order_create(mctx, &order));
1886
 
                for (element = cfg_list_first(rrsetorder);
1887
 
                     element != NULL;
1888
 
                     element = cfg_list_next(element))
1889
 
                {
1890
 
                        const cfg_obj_t *ent = cfg_listelt_value(element);
1891
 
 
1892
 
                        CHECK(configure_order(order, ent));
1893
 
                }
1894
 
                if (view->order != NULL)
1895
 
                        dns_order_detach(&view->order);
1896
 
                dns_order_attach(order, &view->order);
1897
 
                dns_order_detach(&order);
1898
 
        }
1899
 
        /*
1900
 
         * Copy the aclenv object.
1901
 
         */
1902
 
        dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
1903
 
 
1904
 
        /*
1905
 
         * Configure the "match-clients" and "match-destinations" ACL.
1906
 
         */
1907
 
        CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx,
1908
 
                                 ns_g_mctx, &view->matchclients));
1909
 
        CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL,
1910
 
                                 actx, ns_g_mctx, &view->matchdestinations));
1911
 
 
1912
 
        /*
1913
 
         * Configure the "match-recursive-only" option.
1914
 
         */
1915
 
        obj = NULL;
1916
 
        (void)ns_config_get(maps, "match-recursive-only", &obj);
1917
 
        if (obj != NULL && cfg_obj_asboolean(obj))
1918
 
                view->matchrecursiveonly = ISC_TRUE;
1919
 
        else
1920
 
                view->matchrecursiveonly = ISC_FALSE;
1921
 
 
1922
 
        /*
1923
 
         * Configure other configurable data.
1924
 
         */
1925
 
        obj = NULL;
1926
 
        result = ns_config_get(maps, "recursion", &obj);
1927
 
        INSIST(result == ISC_R_SUCCESS);
1928
 
        view->recursion = cfg_obj_asboolean(obj);
1929
 
 
1930
 
        obj = NULL;
1931
 
        result = ns_config_get(maps, "auth-nxdomain", &obj);
1932
 
        INSIST(result == ISC_R_SUCCESS);
1933
 
        view->auth_nxdomain = cfg_obj_asboolean(obj);
1934
 
 
1935
 
        obj = NULL;
1936
 
        result = ns_config_get(maps, "minimal-responses", &obj);
1937
 
        INSIST(result == ISC_R_SUCCESS);
1938
 
        view->minimalresponses = cfg_obj_asboolean(obj);
1939
 
 
1940
 
        obj = NULL;
1941
 
        result = ns_config_get(maps, "transfer-format", &obj);
1942
 
        INSIST(result == ISC_R_SUCCESS);
1943
 
        str = cfg_obj_asstring(obj);
1944
 
        if (strcasecmp(str, "many-answers") == 0)
1945
 
                view->transfer_format = dns_many_answers;
1946
 
        else if (strcasecmp(str, "one-answer") == 0)
1947
 
                view->transfer_format = dns_one_answer;
1948
 
        else
1949
 
                INSIST(0);
1950
 
 
1951
 
        /*
1952
 
         * Set sources where additional data and CNAME/DNAME
1953
 
         * targets for authoritative answers may be found.
1954
 
         */
1955
 
        obj = NULL;
1956
 
        result = ns_config_get(maps, "additional-from-auth", &obj);
1957
 
        INSIST(result == ISC_R_SUCCESS);
1958
 
        view->additionalfromauth = cfg_obj_asboolean(obj);
1959
 
        if (view->recursion && ! view->additionalfromauth) {
1960
 
                cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1961
 
                            "'additional-from-auth no' is only supported "
1962
 
                            "with 'recursion no'");
1963
 
                view->additionalfromauth = ISC_TRUE;
1964
 
        }
1965
 
 
1966
 
        obj = NULL;
1967
 
        result = ns_config_get(maps, "additional-from-cache", &obj);
1968
 
        INSIST(result == ISC_R_SUCCESS);
1969
 
        view->additionalfromcache = cfg_obj_asboolean(obj);
1970
 
        if (view->recursion && ! view->additionalfromcache) {
1971
 
                cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
1972
 
                            "'additional-from-cache no' is only supported "
1973
 
                            "with 'recursion no'");
1974
 
                view->additionalfromcache = ISC_TRUE;
1975
 
        }
1976
 
 
1977
 
        /*
1978
 
         * Set "allow-query-cache", "allow-query-cache-on",
1979
 
         * "allow-recursion", and "allow-recursion-on" acls if
1980
 
         * configured in named.conf.
1981
 
         */
1982
 
        CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL,
1983
 
                                 actx, ns_g_mctx, &view->queryacl));
1984
 
        CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL,
1985
 
                                 actx, ns_g_mctx, &view->queryonacl));
1986
 
        if (view->queryonacl == NULL)
1987
 
                CHECK(configure_view_acl(NULL, ns_g_config,
1988
 
                                         "allow-query-cache-on", NULL, actx,
1989
 
                                         ns_g_mctx, &view->queryonacl));
1990
 
        if (strcmp(view->name, "_bind") != 0) {
1991
 
                CHECK(configure_view_acl(vconfig, config, "allow-recursion",
1992
 
                                         NULL, actx, ns_g_mctx,
1993
 
                                         &view->recursionacl));
1994
 
                CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
1995
 
                                         NULL, actx, ns_g_mctx,
1996
 
                                         &view->recursiononacl));
1997
 
        }
1998
 
 
1999
 
        /*
2000
 
         * "allow-query-cache" inherits from "allow-recursion" if set,
2001
 
         * otherwise from "allow-query" if set.
2002
 
         * "allow-recursion" inherits from "allow-query-cache" if set,
2003
 
         * otherwise from "allow-query" if set.
2004
 
         */
2005
 
        if (view->queryacl == NULL && view->recursionacl != NULL)
2006
 
                dns_acl_attach(view->recursionacl, &view->queryacl);
2007
 
        if (view->queryacl == NULL && view->recursion)
2008
 
                CHECK(configure_view_acl(vconfig, config, "allow-query", NULL,
2009
 
                                         actx, ns_g_mctx, &view->queryacl));
2010
 
        if (view->recursion &&
2011
 
            view->recursionacl == NULL && view->queryacl != NULL)
2012
 
                dns_acl_attach(view->queryacl, &view->recursionacl);
2013
 
 
2014
 
        /*
2015
 
         * Set default "allow-recursion", "allow-recursion-on" and
2016
 
         * "allow-query-cache" acls.
2017
 
         */
2018
 
        if (view->recursionacl == NULL && view->recursion)
2019
 
                CHECK(configure_view_acl(NULL, ns_g_config,
2020
 
                                         "allow-recursion", NULL,
2021
 
                                         actx, ns_g_mctx,
2022
 
                                         &view->recursionacl));
2023
 
        if (view->recursiononacl == NULL && view->recursion)
2024
 
                CHECK(configure_view_acl(NULL, ns_g_config,
2025
 
                                         "allow-recursion-on", NULL,
2026
 
                                         actx, ns_g_mctx,
2027
 
                                         &view->recursiononacl));
2028
 
        if (view->queryacl == NULL) {
2029
 
                if (view->recursion)
2030
 
                        CHECK(configure_view_acl(NULL, ns_g_config,
2031
 
                                                 "allow-query-cache", NULL,
2032
 
                                                 actx, ns_g_mctx,
2033
 
                                                 &view->queryacl));
2034
 
                else {
2035
 
                        if (view->queryacl != NULL)
2036
 
                                dns_acl_detach(&view->queryacl);
2037
 
                        CHECK(dns_acl_none(ns_g_mctx, &view->queryacl));
2038
 
                }
2039
 
        }
2040
 
 
2041
 
        /*
2042
 
         * Filter setting on addresses in the answer section.
2043
 
         */
2044
 
        CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses",
2045
 
                                 "acl", actx, ns_g_mctx, &view->denyansweracl));
2046
 
        CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
2047
 
                                       "except-from", ns_g_mctx,
2048
 
                                       &view->answeracl_exclude));
2049
 
 
2050
 
        /*
2051
 
         * Filter setting on names (CNAME/DNAME targets) in the answer section.
2052
 
         */
2053
 
        CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
2054
 
                                       "name", ns_g_mctx,
2055
 
                                       &view->denyanswernames));
2056
 
        CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
2057
 
                                       "except-from", ns_g_mctx,
2058
 
                                       &view->answernames_exclude));
2059
 
 
2060
 
        /*
2061
 
         * Configure sortlist, if set
2062
 
         */
2063
 
        CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
2064
 
                                      &view->sortlist));
2065
 
 
2066
 
        /*
2067
 
         * Configure default allow-transfer, allow-notify, allow-update
2068
 
         * and allow-update-forwarding ACLs, if set, so they can be
2069
 
         * inherited by zones.
2070
 
         */
2071
 
        if (view->notifyacl == NULL)
2072
 
                CHECK(configure_view_acl(NULL, ns_g_config,
2073
 
                                         "allow-notify", NULL, actx,
2074
 
                                         ns_g_mctx, &view->notifyacl));
2075
 
        if (view->transferacl == NULL)
2076
 
                CHECK(configure_view_acl(NULL, ns_g_config,
2077
 
                                         "allow-transfer", NULL, actx,
2078
 
                                         ns_g_mctx, &view->transferacl));
2079
 
        if (view->updateacl == NULL)
2080
 
                CHECK(configure_view_acl(NULL, ns_g_config,
2081
 
                                         "allow-update", NULL, actx,
2082
 
                                         ns_g_mctx, &view->updateacl));
2083
 
        if (view->upfwdacl == NULL)
2084
 
                CHECK(configure_view_acl(NULL, ns_g_config,
2085
 
                                         "allow-update-forwarding", NULL, actx,
2086
 
                                         ns_g_mctx, &view->upfwdacl));
2087
 
 
2088
 
        obj = NULL;
2089
 
        result = ns_config_get(maps, "request-ixfr", &obj);
2090
 
        INSIST(result == ISC_R_SUCCESS);
2091
 
        view->requestixfr = cfg_obj_asboolean(obj);
2092
 
 
2093
 
        obj = NULL;
2094
 
        result = ns_config_get(maps, "provide-ixfr", &obj);
2095
 
        INSIST(result == ISC_R_SUCCESS);
2096
 
        view->provideixfr = cfg_obj_asboolean(obj);
2097
 
 
2098
 
        obj = NULL;
2099
 
        result = ns_config_get(maps, "request-nsid", &obj);
2100
 
        INSIST(result == ISC_R_SUCCESS);
2101
 
        view->requestnsid = cfg_obj_asboolean(obj);
2102
 
 
2103
 
        obj = NULL;
2104
 
        result = ns_config_get(maps, "max-clients-per-query", &obj);
2105
 
        INSIST(result == ISC_R_SUCCESS);
2106
 
        max_clients_per_query = cfg_obj_asuint32(obj);
2107
 
 
2108
 
        obj = NULL;
2109
 
        result = ns_config_get(maps, "clients-per-query", &obj);
2110
 
        INSIST(result == ISC_R_SUCCESS);
2111
 
        dns_resolver_setclientsperquery(view->resolver,
2112
 
                                        cfg_obj_asuint32(obj),
2113
 
                                        max_clients_per_query);
2114
 
 
2115
 
#ifdef ALLOW_FILTER_AAAA_ON_V4
2116
 
        obj = NULL;
2117
 
        result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
2118
 
        INSIST(result == ISC_R_SUCCESS);
2119
 
        if (cfg_obj_isboolean(obj)) {
2120
 
                if (cfg_obj_asboolean(obj))
2121
 
                        view->v4_aaaa = dns_v4_aaaa_filter;
2122
 
                else
2123
 
                        view->v4_aaaa = dns_v4_aaaa_ok;
2124
 
        } else {
2125
 
                const char *v4_aaaastr = cfg_obj_asstring(obj);
2126
 
                if (strcasecmp(v4_aaaastr, "break-dnssec") == 0)
2127
 
                        view->v4_aaaa = dns_v4_aaaa_break_dnssec;
2128
 
                else
2129
 
                        INSIST(0);
2130
 
        }
2131
 
 
2132
 
#endif
2133
 
        obj = NULL;
2134
 
        result = ns_config_get(maps, "dnssec-enable", &obj);
2135
 
        INSIST(result == ISC_R_SUCCESS);
2136
 
        view->enablednssec = cfg_obj_asboolean(obj);
2137
 
 
2138
 
        obj = NULL;
2139
 
        result = ns_config_get(optionmaps, "dnssec-lookaside", &obj);
2140
 
        if (result == ISC_R_SUCCESS) {
2141
 
                /* If set to "auto", use the version from the defaults */
2142
 
                const cfg_obj_t *dlvobj;
2143
 
                dlvobj = cfg_listelt_value(cfg_list_first(obj));
2144
 
                if (!strcmp(cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain")),
2145
 
                            "auto") &&
2146
 
                    cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) {
2147
 
                        auto_dlv = ISC_TRUE;
2148
 
                        obj = NULL;
2149
 
                        result = cfg_map_get(ns_g_defaults,
2150
 
                                             "dnssec-lookaside", &obj);
2151
 
                }
2152
 
        }
2153
 
 
2154
 
        if (result == ISC_R_SUCCESS) {
2155
 
                for (element = cfg_list_first(obj);
2156
 
                     element != NULL;
2157
 
                     element = cfg_list_next(element))
2158
 
                {
2159
 
                        const char *str;
2160
 
                        isc_buffer_t b;
2161
 
                        dns_name_t *dlv;
2162
 
 
2163
 
                        obj = cfg_listelt_value(element);
2164
 
#if 0
2165
 
                        dns_fixedname_t fixed;
2166
 
                        dns_name_t *name;
2167
 
 
2168
 
                        /*
2169
 
                         * When we support multiple dnssec-lookaside
2170
 
                         * entries this is how to find the domain to be
2171
 
                         * checked. XXXMPA
2172
 
                         */
2173
 
                        dns_fixedname_init(&fixed);
2174
 
                        name = dns_fixedname_name(&fixed);
2175
 
                        str = cfg_obj_asstring(cfg_tuple_get(obj,
2176
 
                                                             "domain"));
2177
 
                        isc_buffer_init(&b, str, strlen(str));
2178
 
                        isc_buffer_add(&b, strlen(str));
2179
 
                        CHECK(dns_name_fromtext(name, &b, dns_rootname,
2180
 
                                                0, NULL));
2181
 
#endif
2182
 
                        str = cfg_obj_asstring(cfg_tuple_get(obj,
2183
 
                                                             "trust-anchor"));
2184
 
                        isc_buffer_init(&b, str, strlen(str));
2185
 
                        isc_buffer_add(&b, strlen(str));
2186
 
                        dlv = dns_fixedname_name(&view->dlv_fixed);
2187
 
                        CHECK(dns_name_fromtext(dlv, &b, dns_rootname,
2188
 
                                                DNS_NAME_DOWNCASE, NULL));
2189
 
                        view->dlv = dns_fixedname_name(&view->dlv_fixed);
2190
 
                }
2191
 
        } else
2192
 
                view->dlv = NULL;
2193
 
 
2194
 
        /*
2195
 
         * For now, there is only one kind of trusted keys, the
2196
 
         * "security roots".
2197
 
         */
2198
 
        CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys,
2199
 
                                        auto_dlv, mctx));
2200
 
        dns_resolver_resetmustbesecure(view->resolver);
2201
 
        obj = NULL;
2202
 
        result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
2203
 
        if (result == ISC_R_SUCCESS)
2204
 
                CHECK(mustbesecure(obj, view->resolver));
2205
 
 
2206
 
        obj = NULL;
2207
 
        result = ns_config_get(maps, "preferred-glue", &obj);
2208
 
        if (result == ISC_R_SUCCESS) {
2209
 
                str = cfg_obj_asstring(obj);
2210
 
                if (strcasecmp(str, "a") == 0)
2211
 
                        view->preferred_glue = dns_rdatatype_a;
2212
 
                else if (strcasecmp(str, "aaaa") == 0)
2213
 
                        view->preferred_glue = dns_rdatatype_aaaa;
2214
 
                else
2215
 
                        view->preferred_glue = 0;
2216
 
        } else
2217
 
                view->preferred_glue = 0;
2218
 
 
2219
 
        obj = NULL;
2220
 
        result = ns_config_get(maps, "root-delegation-only", &obj);
2221
 
        if (result == ISC_R_SUCCESS) {
2222
 
                dns_view_setrootdelonly(view, ISC_TRUE);
2223
 
                if (!cfg_obj_isvoid(obj)) {
2224
 
                        dns_fixedname_t fixed;
2225
 
                        dns_name_t *name;
2226
 
                        isc_buffer_t b;
2227
 
                        const char *str;
2228
 
                        const cfg_obj_t *exclude;
2229
 
 
2230
 
                        dns_fixedname_init(&fixed);
2231
 
                        name = dns_fixedname_name(&fixed);
2232
 
                        for (element = cfg_list_first(obj);
2233
 
                             element != NULL;
2234
 
                             element = cfg_list_next(element)) {
2235
 
                                exclude = cfg_listelt_value(element);
2236
 
                                str = cfg_obj_asstring(exclude);
2237
 
                                isc_buffer_init(&b, str, strlen(str));
2238
 
                                isc_buffer_add(&b, strlen(str));
2239
 
                                CHECK(dns_name_fromtext(name, &b, dns_rootname,
2240
 
                                                        0, NULL));
2241
 
                                CHECK(dns_view_excludedelegationonly(view,
2242
 
                                                                     name));
2243
 
                        }
2244
 
                }
2245
 
        } else
2246
 
                dns_view_setrootdelonly(view, ISC_FALSE);
2247
 
 
2248
 
        /*
2249
 
         * Setup automatic empty zones.  If recursion is off then
2250
 
         * they are disabled by default.
2251
 
         */
2252
 
        obj = NULL;
2253
 
        (void)ns_config_get(maps, "empty-zones-enable", &obj);
2254
 
        (void)ns_config_get(maps, "disable-empty-zone", &disablelist);
2255
 
        if (obj == NULL && disablelist == NULL &&
2256
 
            view->rdclass == dns_rdataclass_in) {
2257
 
                rfc1918 = ISC_FALSE;
2258
 
                empty_zones_enable = view->recursion;
2259
 
        } else if (view->rdclass == dns_rdataclass_in) {
2260
 
                rfc1918 = ISC_TRUE;
2261
 
                if (obj != NULL)
2262
 
                        empty_zones_enable = cfg_obj_asboolean(obj);
2263
 
                else
2264
 
                        empty_zones_enable = view->recursion;
2265
 
        } else {
2266
 
                rfc1918 = ISC_FALSE;
2267
 
                empty_zones_enable = ISC_FALSE;
2268
 
        }
2269
 
        if (empty_zones_enable) {
2270
 
                const char *empty;
2271
 
                int empty_zone = 0;
2272
 
                dns_fixedname_t fixed;
2273
 
                dns_name_t *name;
2274
 
                isc_buffer_t buffer;
2275
 
                const char *str;
2276
 
                char server[DNS_NAME_FORMATSIZE + 1];
2277
 
                char contact[DNS_NAME_FORMATSIZE + 1];
2278
 
                isc_boolean_t logit;
2279
 
                const char *empty_dbtype[4] =
2280
 
                                    { "_builtin", "empty", NULL, NULL };
2281
 
                int empty_dbtypec = 4;
2282
 
                isc_boolean_t zonestats_on;
2283
 
 
2284
 
                dns_fixedname_init(&fixed);
2285
 
                name = dns_fixedname_name(&fixed);
2286
 
 
2287
 
                obj = NULL;
2288
 
                result = ns_config_get(maps, "empty-server", &obj);
2289
 
                if (result == ISC_R_SUCCESS) {
2290
 
                        str = cfg_obj_asstring(obj);
2291
 
                        isc_buffer_init(&buffer, str, strlen(str));
2292
 
                        isc_buffer_add(&buffer, strlen(str));
2293
 
                        CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
2294
 
                                                NULL));
2295
 
                        isc_buffer_init(&buffer, server, sizeof(server) - 1);
2296
 
                        CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
2297
 
                        server[isc_buffer_usedlength(&buffer)] = 0;
2298
 
                        empty_dbtype[2] = server;
2299
 
                } else
2300
 
                        empty_dbtype[2] = "@";
2301
 
 
2302
 
                obj = NULL;
2303
 
                result = ns_config_get(maps, "empty-contact", &obj);
2304
 
                if (result == ISC_R_SUCCESS) {
2305
 
                        str = cfg_obj_asstring(obj);
2306
 
                        isc_buffer_init(&buffer, str, strlen(str));
2307
 
                        isc_buffer_add(&buffer, strlen(str));
2308
 
                        CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
2309
 
                                                NULL));
2310
 
                        isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
2311
 
                        CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
2312
 
                        contact[isc_buffer_usedlength(&buffer)] = 0;
2313
 
                        empty_dbtype[3] = contact;
2314
 
                } else
2315
 
                        empty_dbtype[3] = ".";
2316
 
 
2317
 
                obj = NULL;
2318
 
                result = ns_config_get(maps, "zone-statistics", &obj);
2319
 
                INSIST(result == ISC_R_SUCCESS);
2320
 
                zonestats_on = cfg_obj_asboolean(obj);
2321
 
 
2322
 
                logit = ISC_TRUE;
2323
 
                for (empty = empty_zones[empty_zone].zone;
2324
 
                     empty != NULL;
2325
 
                     empty = empty_zones[++empty_zone].zone)
2326
 
                {
2327
 
                        dns_forwarders_t *forwarders = NULL;
2328
 
                        dns_view_t *pview = NULL;
2329
 
 
2330
 
                        isc_buffer_init(&buffer, empty, strlen(empty));
2331
 
                        isc_buffer_add(&buffer, strlen(empty));
2332
 
                        /*
2333
 
                         * Look for zone on drop list.
2334
 
                         */
2335
 
                        CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
2336
 
                                                NULL));
2337
 
                        if (disablelist != NULL &&
2338
 
                            on_disable_list(disablelist, name))
2339
 
                                continue;
2340
 
 
2341
 
                        /*
2342
 
                         * This zone already exists.
2343
 
                         */
2344
 
                        (void)dns_view_findzone(view, name, &zone);
2345
 
                        if (zone != NULL) {
2346
 
                                CHECK(setquerystats(zone, mctx, zonestats_on));
2347
 
                                dns_zone_detach(&zone);
2348
 
                                continue;
2349
 
                        }
2350
 
 
2351
 
                        /*
2352
 
                         * If we would forward this name don't add a
2353
 
                         * empty zone for it.
2354
 
                         */
2355
 
                        result = dns_fwdtable_find(view->fwdtable, name,
2356
 
                                                   &forwarders);
2357
 
                        if (result == ISC_R_SUCCESS &&
2358
 
                            forwarders->fwdpolicy == dns_fwdpolicy_only)
2359
 
                                continue;
2360
 
 
2361
 
                        if (!rfc1918 && empty_zones[empty_zone].rfc1918) {
2362
 
                                if (logit) {
2363
 
                                        isc_log_write(ns_g_lctx,
2364
 
                                                      NS_LOGCATEGORY_GENERAL,
2365
 
                                                      NS_LOGMODULE_SERVER,
2366
 
                                                      ISC_LOG_WARNING,
2367
 
                                                      "Warning%s%s: "
2368
 
                                                      "'empty-zones-enable/"
2369
 
                                                      "disable-empty-zone' "
2370
 
                                                      "not set: disabling "
2371
 
                                                      "RFC 1918 empty zones",
2372
 
                                                      sep, viewname);
2373
 
                                        logit = ISC_FALSE;
2374
 
                                }
2375
 
                                continue;
2376
 
                        }
2377
 
 
2378
 
                        /*
2379
 
                         * See if we can re-use a existing zone.
2380
 
                         */
2381
 
                        result = dns_viewlist_find(&ns_g_server->viewlist,
2382
 
                                                   view->name, view->rdclass,
2383
 
                                                   &pview);
2384
 
                        if (result != ISC_R_NOTFOUND &&
2385
 
                            result != ISC_R_SUCCESS)
2386
 
                                goto cleanup;
2387
 
 
2388
 
                        if (pview != NULL) {
2389
 
                                (void)dns_view_findzone(pview, name, &zone);
2390
 
                                dns_view_detach(&pview);
2391
 
                                if (zone != NULL)
2392
 
                                        check_dbtype(&zone, empty_dbtypec,
2393
 
                                                     empty_dbtype, mctx);
2394
 
                                if (zone != NULL) {
2395
 
                                        dns_zone_setview(zone, view);
2396
 
                                        CHECK(dns_view_addzone(view, zone));
2397
 
                                        CHECK(setquerystats(zone, mctx,
2398
 
                                                            zonestats_on));
2399
 
                                        dns_zone_detach(&zone);
2400
 
                                        continue;
2401
 
                                }
2402
 
                        }
2403
 
 
2404
 
                        CHECK(dns_zone_create(&zone, mctx));
2405
 
                        CHECK(dns_zone_setorigin(zone, name));
2406
 
                        dns_zone_setview(zone, view);
2407
 
                        CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
2408
 
                        dns_zone_setclass(zone, view->rdclass);
2409
 
                        dns_zone_settype(zone, dns_zone_master);
2410
 
                        dns_zone_setstats(zone, ns_g_server->zonestats);
2411
 
                        CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
2412
 
                                                 empty_dbtype));
2413
 
                        if (view->queryacl != NULL)
2414
 
                                dns_zone_setqueryacl(zone, view->queryacl);
2415
 
                        if (view->queryonacl != NULL)
2416
 
                                dns_zone_setqueryonacl(zone, view->queryonacl);
2417
 
                        dns_zone_setdialup(zone, dns_dialuptype_no);
2418
 
                        dns_zone_setnotifytype(zone, dns_notifytype_no);
2419
 
                        dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS,
2420
 
                                           ISC_TRUE);
2421
 
                        CHECK(setquerystats(zone, mctx, zonestats_on));
2422
 
                        CHECK(dns_view_addzone(view, zone));
2423
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2424
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
2425
 
                                      "automatic empty zone%s%s: %s",
2426
 
                                      sep, viewname,  empty);
2427
 
                        dns_zone_detach(&zone);
2428
 
                }
2429
 
        }
2430
 
 
2431
 
        result = ISC_R_SUCCESS;
2432
 
 
2433
 
 cleanup:
2434
 
        if (ring != NULL)
2435
 
                dns_tsigkeyring_destroy(&ring);
2436
 
        if (zone != NULL)
2437
 
                dns_zone_detach(&zone);
2438
 
        if (dispatch4 != NULL)
2439
 
                dns_dispatch_detach(&dispatch4);
2440
 
        if (dispatch6 != NULL)
2441
 
                dns_dispatch_detach(&dispatch6);
2442
 
        if (resstats != NULL)
2443
 
                isc_stats_detach(&resstats);
2444
 
        if (resquerystats != NULL)
2445
 
                dns_stats_detach(&resquerystats);
2446
 
        if (order != NULL)
2447
 
                dns_order_detach(&order);
2448
 
        if (cmctx != NULL)
2449
 
                isc_mem_detach(&cmctx);
2450
 
 
2451
 
        if (cache != NULL)
2452
 
                dns_cache_detach(&cache);
2453
 
 
2454
 
        return (result);
2455
 
}
2456
 
 
2457
 
static isc_result_t
2458
 
configure_hints(dns_view_t *view, const char *filename) {
2459
 
        isc_result_t result;
2460
 
        dns_db_t *db;
2461
 
 
2462
 
        db = NULL;
2463
 
        result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
2464
 
        if (result == ISC_R_SUCCESS) {
2465
 
                dns_view_sethints(view, db);
2466
 
                dns_db_detach(&db);
2467
 
        }
2468
 
 
2469
 
        return (result);
2470
 
}
2471
 
 
2472
 
static isc_result_t
2473
 
configure_alternates(const cfg_obj_t *config, dns_view_t *view,
2474
 
                     const cfg_obj_t *alternates)
2475
 
{
2476
 
        const cfg_obj_t *portobj;
2477
 
        const cfg_obj_t *addresses;
2478
 
        const cfg_listelt_t *element;
2479
 
        isc_result_t result = ISC_R_SUCCESS;
2480
 
        in_port_t port;
2481
 
 
2482
 
        /*
2483
 
         * Determine which port to send requests to.
2484
 
         */
2485
 
        if (ns_g_lwresdonly && ns_g_port != 0)
2486
 
                port = ns_g_port;
2487
 
        else
2488
 
                CHECKM(ns_config_getport(config, &port), "port");
2489
 
 
2490
 
        if (alternates != NULL) {
2491
 
                portobj = cfg_tuple_get(alternates, "port");
2492
 
                if (cfg_obj_isuint32(portobj)) {
2493
 
                        isc_uint32_t val = cfg_obj_asuint32(portobj);
2494
 
                        if (val > ISC_UINT16_MAX) {
2495
 
                                cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
2496
 
                                            "port '%u' out of range", val);
2497
 
                                return (ISC_R_RANGE);
2498
 
                        }
2499
 
                        port = (in_port_t) val;
2500
 
                }
2501
 
        }
2502
 
 
2503
 
        addresses = NULL;
2504
 
        if (alternates != NULL)
2505
 
                addresses = cfg_tuple_get(alternates, "addresses");
2506
 
 
2507
 
        for (element = cfg_list_first(addresses);
2508
 
             element != NULL;
2509
 
             element = cfg_list_next(element))
2510
 
        {
2511
 
                const cfg_obj_t *alternate = cfg_listelt_value(element);
2512
 
                isc_sockaddr_t sa;
2513
 
 
2514
 
                if (!cfg_obj_issockaddr(alternate)) {
2515
 
                        dns_fixedname_t fixed;
2516
 
                        dns_name_t *name;
2517
 
                        const char *str = cfg_obj_asstring(cfg_tuple_get(
2518
 
                                                           alternate, "name"));
2519
 
                        isc_buffer_t buffer;
2520
 
                        in_port_t myport = port;
2521
 
 
2522
 
                        isc_buffer_init(&buffer, str, strlen(str));
2523
 
                        isc_buffer_add(&buffer, strlen(str));
2524
 
                        dns_fixedname_init(&fixed);
2525
 
                        name = dns_fixedname_name(&fixed);
2526
 
                        CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
2527
 
                                                NULL));
2528
 
 
2529
 
                        portobj = cfg_tuple_get(alternate, "port");
2530
 
                        if (cfg_obj_isuint32(portobj)) {
2531
 
                                isc_uint32_t val = cfg_obj_asuint32(portobj);
2532
 
                                if (val > ISC_UINT16_MAX) {
2533
 
                                        cfg_obj_log(portobj, ns_g_lctx,
2534
 
                                                    ISC_LOG_ERROR,
2535
 
                                                    "port '%u' out of range",
2536
 
                                                     val);
2537
 
                                        return (ISC_R_RANGE);
2538
 
                                }
2539
 
                                myport = (in_port_t) val;
2540
 
                        }
2541
 
                        CHECK(dns_resolver_addalternate(view->resolver, NULL,
2542
 
                                                        name, myport));
2543
 
                        continue;
2544
 
                }
2545
 
 
2546
 
                sa = *cfg_obj_assockaddr(alternate);
2547
 
                if (isc_sockaddr_getport(&sa) == 0)
2548
 
                        isc_sockaddr_setport(&sa, port);
2549
 
                CHECK(dns_resolver_addalternate(view->resolver, &sa,
2550
 
                                                NULL, 0));
2551
 
        }
2552
 
 
2553
 
 cleanup:
2554
 
        return (result);
2555
 
}
2556
 
 
2557
 
static isc_result_t
2558
 
configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
2559
 
                  const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype)
2560
 
{
2561
 
        const cfg_obj_t *portobj;
2562
 
        const cfg_obj_t *faddresses;
2563
 
        const cfg_listelt_t *element;
2564
 
        dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
2565
 
        isc_sockaddrlist_t addresses;
2566
 
        isc_sockaddr_t *sa;
2567
 
        isc_result_t result;
2568
 
        in_port_t port;
2569
 
 
2570
 
        ISC_LIST_INIT(addresses);
2571
 
 
2572
 
        /*
2573
 
         * Determine which port to send forwarded requests to.
2574
 
         */
2575
 
        if (ns_g_lwresdonly && ns_g_port != 0)
2576
 
                port = ns_g_port;
2577
 
        else
2578
 
                CHECKM(ns_config_getport(config, &port), "port");
2579
 
 
2580
 
        if (forwarders != NULL) {
2581
 
                portobj = cfg_tuple_get(forwarders, "port");
2582
 
                if (cfg_obj_isuint32(portobj)) {
2583
 
                        isc_uint32_t val = cfg_obj_asuint32(portobj);
2584
 
                        if (val > ISC_UINT16_MAX) {
2585
 
                                cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
2586
 
                                            "port '%u' out of range", val);
2587
 
                                return (ISC_R_RANGE);
2588
 
                        }
2589
 
                        port = (in_port_t) val;
2590
 
                }
2591
 
        }
2592
 
 
2593
 
        faddresses = NULL;
2594
 
        if (forwarders != NULL)
2595
 
                faddresses = cfg_tuple_get(forwarders, "addresses");
2596
 
 
2597
 
        for (element = cfg_list_first(faddresses);
2598
 
             element != NULL;
2599
 
             element = cfg_list_next(element))
2600
 
        {
2601
 
                const cfg_obj_t *forwarder = cfg_listelt_value(element);
2602
 
                sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
2603
 
                if (sa == NULL) {
2604
 
                        result = ISC_R_NOMEMORY;
2605
 
                        goto cleanup;
2606
 
                }
2607
 
                *sa = *cfg_obj_assockaddr(forwarder);
2608
 
                if (isc_sockaddr_getport(sa) == 0)
2609
 
                        isc_sockaddr_setport(sa, port);
2610
 
                ISC_LINK_INIT(sa, link);
2611
 
                ISC_LIST_APPEND(addresses, sa, link);
2612
 
        }
2613
 
 
2614
 
        if (ISC_LIST_EMPTY(addresses)) {
2615
 
                if (forwardtype != NULL)
2616
 
                        cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
2617
 
                                    "no forwarders seen; disabling "
2618
 
                                    "forwarding");
2619
 
                fwdpolicy = dns_fwdpolicy_none;
2620
 
        } else {
2621
 
                if (forwardtype == NULL)
2622
 
                        fwdpolicy = dns_fwdpolicy_first;
2623
 
                else {
2624
 
                        const char *forwardstr = cfg_obj_asstring(forwardtype);
2625
 
                        if (strcasecmp(forwardstr, "first") == 0)
2626
 
                                fwdpolicy = dns_fwdpolicy_first;
2627
 
                        else if (strcasecmp(forwardstr, "only") == 0)
2628
 
                                fwdpolicy = dns_fwdpolicy_only;
2629
 
                        else
2630
 
                                INSIST(0);
2631
 
                }
2632
 
        }
2633
 
 
2634
 
        result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
2635
 
                                  fwdpolicy);
2636
 
        if (result != ISC_R_SUCCESS) {
2637
 
                char namebuf[DNS_NAME_FORMATSIZE];
2638
 
                dns_name_format(origin, namebuf, sizeof(namebuf));
2639
 
                cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
2640
 
                            "could not set up forwarding for domain '%s': %s",
2641
 
                            namebuf, isc_result_totext(result));
2642
 
                goto cleanup;
2643
 
        }
2644
 
 
2645
 
        result = ISC_R_SUCCESS;
2646
 
 
2647
 
 cleanup:
2648
 
 
2649
 
        while (!ISC_LIST_EMPTY(addresses)) {
2650
 
                sa = ISC_LIST_HEAD(addresses);
2651
 
                ISC_LIST_UNLINK(addresses, sa, link);
2652
 
                isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
2653
 
        }
2654
 
 
2655
 
        return (result);
2656
 
}
2657
 
 
2658
 
/*
2659
 
 * Create a new view and add it to the list.
2660
 
 *
2661
 
 * If 'vconfig' is NULL, create the default view.
2662
 
 *
2663
 
 * The view created is attached to '*viewp'.
2664
 
 */
2665
 
static isc_result_t
2666
 
create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
2667
 
            dns_view_t **viewp)
2668
 
{
2669
 
        isc_result_t result;
2670
 
        const char *viewname;
2671
 
        dns_rdataclass_t viewclass;
2672
 
        dns_view_t *view = NULL;
2673
 
 
2674
 
        if (vconfig != NULL) {
2675
 
                const cfg_obj_t *classobj = NULL;
2676
 
 
2677
 
                viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
2678
 
                classobj = cfg_tuple_get(vconfig, "class");
2679
 
                result = ns_config_getclass(classobj, dns_rdataclass_in,
2680
 
                                            &viewclass);
2681
 
        } else {
2682
 
                viewname = "_default";
2683
 
                viewclass = dns_rdataclass_in;
2684
 
        }
2685
 
        result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
2686
 
        if (result == ISC_R_SUCCESS)
2687
 
                return (ISC_R_EXISTS);
2688
 
        if (result != ISC_R_NOTFOUND)
2689
 
                return (result);
2690
 
        INSIST(view == NULL);
2691
 
 
2692
 
        result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
2693
 
        if (result != ISC_R_SUCCESS)
2694
 
                return (result);
2695
 
 
2696
 
        ISC_LIST_APPEND(*viewlist, view, link);
2697
 
        dns_view_attach(view, viewp);
2698
 
        return (ISC_R_SUCCESS);
2699
 
}
2700
 
 
2701
 
/*
2702
 
 * Configure or reconfigure a zone.
2703
 
 */
2704
 
static isc_result_t
2705
 
configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
2706
 
               const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
2707
 
               cfg_aclconfctx_t *aclconf)
2708
 
{
2709
 
        dns_view_t *pview = NULL;       /* Production view */
2710
 
        dns_zone_t *zone = NULL;        /* New or reused zone */
2711
 
        dns_zone_t *dupzone = NULL;
2712
 
        const cfg_obj_t *options = NULL;
2713
 
        const cfg_obj_t *zoptions = NULL;
2714
 
        const cfg_obj_t *typeobj = NULL;
2715
 
        const cfg_obj_t *forwarders = NULL;
2716
 
        const cfg_obj_t *forwardtype = NULL;
2717
 
        const cfg_obj_t *only = NULL;
2718
 
        isc_result_t result;
2719
 
        isc_result_t tresult;
2720
 
        isc_buffer_t buffer;
2721
 
        dns_fixedname_t fixorigin;
2722
 
        dns_name_t *origin;
2723
 
        const char *zname;
2724
 
        dns_rdataclass_t zclass;
2725
 
        const char *ztypestr;
2726
 
 
2727
 
        options = NULL;
2728
 
        (void)cfg_map_get(config, "options", &options);
2729
 
 
2730
 
        zoptions = cfg_tuple_get(zconfig, "options");
2731
 
 
2732
 
        /*
2733
 
         * Get the zone origin as a dns_name_t.
2734
 
         */
2735
 
        zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
2736
 
        isc_buffer_init(&buffer, zname, strlen(zname));
2737
 
        isc_buffer_add(&buffer, strlen(zname));
2738
 
        dns_fixedname_init(&fixorigin);
2739
 
        CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
2740
 
                                &buffer, dns_rootname, 0, NULL));
2741
 
        origin = dns_fixedname_name(&fixorigin);
2742
 
 
2743
 
        CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
2744
 
                                 view->rdclass, &zclass));
2745
 
        if (zclass != view->rdclass) {
2746
 
                const char *vname = NULL;
2747
 
                if (vconfig != NULL)
2748
 
                        vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
2749
 
                                                               "name"));
2750
 
                else
2751
 
                        vname = "<default view>";
2752
 
 
2753
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2754
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
2755
 
                              "zone '%s': wrong class for view '%s'",
2756
 
                              zname, vname);
2757
 
                result = ISC_R_FAILURE;
2758
 
                goto cleanup;
2759
 
        }
2760
 
 
2761
 
        (void)cfg_map_get(zoptions, "type", &typeobj);
2762
 
        if (typeobj == NULL) {
2763
 
                cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
2764
 
                            "zone '%s' 'type' not specified", zname);
2765
 
                return (ISC_R_FAILURE);
2766
 
        }
2767
 
        ztypestr = cfg_obj_asstring(typeobj);
2768
 
 
2769
 
        /*
2770
 
         * "hints zones" aren't zones.  If we've got one,
2771
 
         * configure it and return.
2772
 
         */
2773
 
        if (strcasecmp(ztypestr, "hint") == 0) {
2774
 
                const cfg_obj_t *fileobj = NULL;
2775
 
                if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
2776
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2777
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
2778
 
                                      "zone '%s': 'file' not specified",
2779
 
                                      zname);
2780
 
                        result = ISC_R_FAILURE;
2781
 
                        goto cleanup;
2782
 
                }
2783
 
                if (dns_name_equal(origin, dns_rootname)) {
2784
 
                        const char *hintsfile = cfg_obj_asstring(fileobj);
2785
 
 
2786
 
                        result = configure_hints(view, hintsfile);
2787
 
                        if (result != ISC_R_SUCCESS) {
2788
 
                                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2789
 
                                              NS_LOGMODULE_SERVER,
2790
 
                                              ISC_LOG_ERROR,
2791
 
                                              "could not configure root hints "
2792
 
                                              "from '%s': %s", hintsfile,
2793
 
                                              isc_result_totext(result));
2794
 
                                goto cleanup;
2795
 
                        }
2796
 
                        /*
2797
 
                         * Hint zones may also refer to delegation only points.
2798
 
                         */
2799
 
                        only = NULL;
2800
 
                        tresult = cfg_map_get(zoptions, "delegation-only",
2801
 
                                              &only);
2802
 
                        if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
2803
 
                                CHECK(dns_view_adddelegationonly(view, origin));
2804
 
                } else {
2805
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2806
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
2807
 
                                      "ignoring non-root hint zone '%s'",
2808
 
                                      zname);
2809
 
                        result = ISC_R_SUCCESS;
2810
 
                }
2811
 
                /* Skip ordinary zone processing. */
2812
 
                goto cleanup;
2813
 
        }
2814
 
 
2815
 
        /*
2816
 
         * "forward zones" aren't zones either.  Translate this syntax into
2817
 
         * the appropriate selective forwarding configuration and return.
2818
 
         */
2819
 
        if (strcasecmp(ztypestr, "forward") == 0) {
2820
 
                forwardtype = NULL;
2821
 
                forwarders = NULL;
2822
 
 
2823
 
                (void)cfg_map_get(zoptions, "forward", &forwardtype);
2824
 
                (void)cfg_map_get(zoptions, "forwarders", &forwarders);
2825
 
                result = configure_forward(config, view, origin, forwarders,
2826
 
                                           forwardtype);
2827
 
                goto cleanup;
2828
 
        }
2829
 
 
2830
 
        /*
2831
 
         * "delegation-only zones" aren't zones either.
2832
 
         */
2833
 
        if (strcasecmp(ztypestr, "delegation-only") == 0) {
2834
 
                result = dns_view_adddelegationonly(view, origin);
2835
 
                goto cleanup;
2836
 
        }
2837
 
 
2838
 
        /*
2839
 
         * Check for duplicates in the new zone table.
2840
 
         */
2841
 
        result = dns_view_findzone(view, origin, &dupzone);
2842
 
        if (result == ISC_R_SUCCESS) {
2843
 
                /*
2844
 
                 * We already have this zone!
2845
 
                 */
2846
 
                cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
2847
 
                            "zone '%s' already exists", zname);
2848
 
                dns_zone_detach(&dupzone);
2849
 
                result = ISC_R_EXISTS;
2850
 
                goto cleanup;
2851
 
        }
2852
 
        INSIST(dupzone == NULL);
2853
 
 
2854
 
        /*
2855
 
         * See if we can reuse an existing zone.  This is
2856
 
         * only possible if all of these are true:
2857
 
         *   - The zone's view exists
2858
 
         *   - A zone with the right name exists in the view
2859
 
         *   - The zone is compatible with the config
2860
 
         *     options (e.g., an existing master zone cannot
2861
 
         *     be reused if the options specify a slave zone)
2862
 
         */
2863
 
        result = dns_viewlist_find(&ns_g_server->viewlist,
2864
 
                                   view->name, view->rdclass,
2865
 
                                   &pview);
2866
 
        if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
2867
 
                goto cleanup;
2868
 
        if (pview != NULL)
2869
 
                result = dns_view_findzone(pview, origin, &zone);
2870
 
        if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
2871
 
                goto cleanup;
2872
 
        if (zone != NULL && !ns_zone_reusable(zone, zconfig))
2873
 
                dns_zone_detach(&zone);
2874
 
 
2875
 
        if (zone != NULL) {
2876
 
                /*
2877
 
                 * We found a reusable zone.  Make it use the
2878
 
                 * new view.
2879
 
                 */
2880
 
                dns_zone_setview(zone, view);
2881
 
                if (view->acache != NULL)
2882
 
                        dns_zone_setacache(zone, view->acache);
2883
 
        } else {
2884
 
                /*
2885
 
                 * We cannot reuse an existing zone, we have
2886
 
                 * to create a new one.
2887
 
                 */
2888
 
                CHECK(dns_zone_create(&zone, mctx));
2889
 
                CHECK(dns_zone_setorigin(zone, origin));
2890
 
                dns_zone_setview(zone, view);
2891
 
                if (view->acache != NULL)
2892
 
                        dns_zone_setacache(zone, view->acache);
2893
 
                CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
2894
 
                dns_zone_setstats(zone, ns_g_server->zonestats);
2895
 
        }
2896
 
 
2897
 
        /*
2898
 
         * If the zone contains a 'forwarders' statement, configure
2899
 
         * selective forwarding.
2900
 
         */
2901
 
        forwarders = NULL;
2902
 
        if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
2903
 
        {
2904
 
                forwardtype = NULL;
2905
 
                (void)cfg_map_get(zoptions, "forward", &forwardtype);
2906
 
                CHECK(configure_forward(config, view, origin, forwarders,
2907
 
                                        forwardtype));
2908
 
        }
2909
 
 
2910
 
        /*
2911
 
         * Stub and forward zones may also refer to delegation only points.
2912
 
         */
2913
 
        only = NULL;
2914
 
        if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
2915
 
        {
2916
 
                if (cfg_obj_asboolean(only))
2917
 
                        CHECK(dns_view_adddelegationonly(view, origin));
2918
 
        }
2919
 
 
2920
 
        /*
2921
 
         * Configure the zone.
2922
 
         */
2923
 
        CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
2924
 
 
2925
 
        /*
2926
 
         * Add the zone to its view in the new view list.
2927
 
         */
2928
 
        CHECK(dns_view_addzone(view, zone));
2929
 
 
2930
 
 cleanup:
2931
 
        if (zone != NULL)
2932
 
                dns_zone_detach(&zone);
2933
 
        if (pview != NULL)
2934
 
                dns_view_detach(&pview);
2935
 
 
2936
 
        return (result);
2937
 
}
2938
 
 
2939
 
/*
2940
 
 * Configure built-in zone for storing managed-key data.
2941
 
 */
2942
 
 
2943
 
#define KEYZONE "managed-keys.bind"
2944
 
#define MKEYS ".mkeys"
2945
 
 
2946
 
static isc_result_t
2947
 
add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
2948
 
        isc_result_t result;
2949
 
        dns_zone_t *zone = NULL;
2950
 
        dns_acl_t *none = NULL;
2951
 
        char filename[PATH_MAX];
2952
 
        char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(MKEYS)];
2953
 
        int n;
2954
 
 
2955
 
        REQUIRE(view != NULL);
2956
 
 
2957
 
        CHECK(dns_zone_create(&zone, mctx));
2958
 
 
2959
 
        CHECK(dns_zone_setorigin(zone, dns_rootname));
2960
 
 
2961
 
        isc_sha256_data((void *)view->name, strlen(view->name), buffer);
2962
 
        strcat(buffer, MKEYS);
2963
 
        n = snprintf(filename, sizeof(filename), "%s%s%s",
2964
 
                     directory ? directory : "", directory ? "/" : "",
2965
 
                     strcmp(view->name, "_default") == 0 ? KEYZONE : buffer);
2966
 
        if (n < 0 || (size_t)n >= sizeof(filename)) {
2967
 
                result = (n < 0) ? ISC_R_FAILURE : ISC_R_NOSPACE;
2968
 
                goto cleanup;
2969
 
        }
2970
 
        CHECK(dns_zone_setfile(zone, filename));
2971
 
 
2972
 
        dns_zone_setview(zone, view);
2973
 
        dns_zone_settype(zone, dns_zone_key);
2974
 
        dns_zone_setclass(zone, view->rdclass);
2975
 
 
2976
 
        CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
2977
 
 
2978
 
        if (view->acache != NULL)
2979
 
                dns_zone_setacache(zone, view->acache);
2980
 
 
2981
 
        CHECK(dns_acl_none(mctx, &none));
2982
 
        dns_zone_setqueryacl(zone, none);
2983
 
        dns_zone_setqueryonacl(zone, none);
2984
 
        dns_acl_detach(&none);
2985
 
 
2986
 
        dns_zone_setdialup(zone, dns_dialuptype_no);
2987
 
        dns_zone_setnotifytype(zone, dns_notifytype_no);
2988
 
        dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
2989
 
        dns_zone_setjournalsize(zone, 0);
2990
 
 
2991
 
        dns_zone_setstats(zone, ns_g_server->zonestats);
2992
 
        CHECK(setquerystats(zone, mctx, ISC_FALSE));
2993
 
 
2994
 
        if (view->managed_keys != NULL)
2995
 
                dns_zone_detach(&view->managed_keys);
2996
 
        dns_zone_attach(zone, &view->managed_keys);
2997
 
 
2998
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
2999
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3000
 
                      "set up managed keys zone for view %s, file '%s'",
3001
 
                      view->name, filename);
3002
 
 
3003
 
cleanup:
3004
 
        if (zone != NULL)
3005
 
                dns_zone_detach(&zone);
3006
 
        if (none != NULL)
3007
 
                dns_acl_detach(&none);
3008
 
 
3009
 
        return (result);
3010
 
}
3011
 
 
3012
 
/*
3013
 
 * Configure a single server quota.
3014
 
 */
3015
 
static void
3016
 
configure_server_quota(const cfg_obj_t **maps, const char *name,
3017
 
                       isc_quota_t *quota)
3018
 
{
3019
 
        const cfg_obj_t *obj = NULL;
3020
 
        isc_result_t result;
3021
 
 
3022
 
        result = ns_config_get(maps, name, &obj);
3023
 
        INSIST(result == ISC_R_SUCCESS);
3024
 
        isc_quota_max(quota, cfg_obj_asuint32(obj));
3025
 
}
3026
 
 
3027
 
/*
3028
 
 * This function is called as soon as the 'directory' statement has been
3029
 
 * parsed.  This can be extended to support other options if necessary.
3030
 
 */
3031
 
static isc_result_t
3032
 
directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
3033
 
        isc_result_t result;
3034
 
        const char *directory;
3035
 
 
3036
 
        REQUIRE(strcasecmp("directory", clausename) == 0);
3037
 
 
3038
 
        UNUSED(arg);
3039
 
        UNUSED(clausename);
3040
 
 
3041
 
        /*
3042
 
         * Change directory.
3043
 
         */
3044
 
        directory = cfg_obj_asstring(obj);
3045
 
 
3046
 
        if (! isc_file_ischdiridempotent(directory))
3047
 
                cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
3048
 
                            "option 'directory' contains relative path '%s'",
3049
 
                            directory);
3050
 
 
3051
 
        result = isc_dir_chdir(directory);
3052
 
        if (result != ISC_R_SUCCESS) {
3053
 
                cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
3054
 
                            "change directory to '%s' failed: %s",
3055
 
                            directory, isc_result_totext(result));
3056
 
                return (result);
3057
 
        }
3058
 
 
3059
 
        return (ISC_R_SUCCESS);
3060
 
}
3061
 
 
3062
 
static void
3063
 
scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
3064
 
        isc_boolean_t match_mapped = server->aclenv.match_mapped;
3065
 
 
3066
 
        ns_interfacemgr_scan(server->interfacemgr, verbose);
3067
 
        /*
3068
 
         * Update the "localhost" and "localnets" ACLs to match the
3069
 
         * current set of network interfaces.
3070
 
         */
3071
 
        dns_aclenv_copy(&server->aclenv,
3072
 
                        ns_interfacemgr_getaclenv(server->interfacemgr));
3073
 
 
3074
 
        server->aclenv.match_mapped = match_mapped;
3075
 
}
3076
 
 
3077
 
static isc_result_t
3078
 
add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
3079
 
              isc_boolean_t wcardport_ok)
3080
 
{
3081
 
        ns_listenelt_t *lelt = NULL;
3082
 
        dns_acl_t *src_acl = NULL;
3083
 
        isc_result_t result;
3084
 
        isc_sockaddr_t any_sa6;
3085
 
        isc_netaddr_t netaddr;
3086
 
 
3087
 
        REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
3088
 
 
3089
 
        isc_sockaddr_any6(&any_sa6);
3090
 
        if (!isc_sockaddr_equal(&any_sa6, addr) &&
3091
 
            (wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
3092
 
                isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
3093
 
 
3094
 
                result = dns_acl_create(mctx, 0, &src_acl);
3095
 
                if (result != ISC_R_SUCCESS)
3096
 
                        return (result);
3097
 
 
3098
 
                result = dns_iptable_addprefix(src_acl->iptable,
3099
 
                                               &netaddr, 128, ISC_TRUE);
3100
 
                if (result != ISC_R_SUCCESS)
3101
 
                        goto clean;
3102
 
 
3103
 
                result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
3104
 
                                             src_acl, &lelt);
3105
 
                if (result != ISC_R_SUCCESS)
3106
 
                        goto clean;
3107
 
                ISC_LIST_APPEND(list->elts, lelt, link);
3108
 
        }
3109
 
 
3110
 
        return (ISC_R_SUCCESS);
3111
 
 
3112
 
 clean:
3113
 
        INSIST(lelt == NULL);
3114
 
        dns_acl_detach(&src_acl);
3115
 
 
3116
 
        return (result);
3117
 
}
3118
 
 
3119
 
/*
3120
 
 * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
3121
 
 * to update the listening interfaces accordingly.
3122
 
 * We currently only consider IPv6, because this only affects IPv6 wildcard
3123
 
 * sockets.
3124
 
 */
3125
 
static void
3126
 
adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
3127
 
        isc_result_t result;
3128
 
        ns_listenlist_t *list = NULL;
3129
 
        dns_view_t *view;
3130
 
        dns_zone_t *zone, *next;
3131
 
        isc_sockaddr_t addr, *addrp;
3132
 
 
3133
 
        result = ns_listenlist_create(mctx, &list);
3134
 
        if (result != ISC_R_SUCCESS)
3135
 
                return;
3136
 
 
3137
 
        for (view = ISC_LIST_HEAD(server->viewlist);
3138
 
             view != NULL;
3139
 
             view = ISC_LIST_NEXT(view, link)) {
3140
 
                dns_dispatch_t *dispatch6;
3141
 
 
3142
 
                dispatch6 = dns_resolver_dispatchv6(view->resolver);
3143
 
                if (dispatch6 == NULL)
3144
 
                        continue;
3145
 
                result = dns_dispatch_getlocaladdress(dispatch6, &addr);
3146
 
                if (result != ISC_R_SUCCESS)
3147
 
                        goto fail;
3148
 
 
3149
 
                /*
3150
 
                 * We always add non-wildcard address regardless of whether
3151
 
                 * the port is 'any' (the fourth arg is TRUE): if the port is
3152
 
                 * specific, we need to add it since it may conflict with a
3153
 
                 * listening interface; if it's zero, we'll dynamically open
3154
 
                 * query ports, and some of them may override an existing
3155
 
                 * wildcard IPv6 port.
3156
 
                 */
3157
 
                result = add_listenelt(mctx, list, &addr, ISC_TRUE);
3158
 
                if (result != ISC_R_SUCCESS)
3159
 
                        goto fail;
3160
 
        }
3161
 
 
3162
 
        zone = NULL;
3163
 
        for (result = dns_zone_first(server->zonemgr, &zone);
3164
 
             result == ISC_R_SUCCESS;
3165
 
             next = NULL, result = dns_zone_next(zone, &next), zone = next) {
3166
 
                dns_view_t *zoneview;
3167
 
 
3168
 
                /*
3169
 
                 * At this point the zone list may contain a stale zone
3170
 
                 * just removed from the configuration.  To see the validity,
3171
 
                 * check if the corresponding view is in our current view list.
3172
 
                 * There may also be old zones that are still in the process
3173
 
                 * of shutting down and have detached from their old view
3174
 
                 * (zoneview == NULL).
3175
 
                 */
3176
 
                zoneview = dns_zone_getview(zone);
3177
 
                if (zoneview == NULL)
3178
 
                        continue;
3179
 
                for (view = ISC_LIST_HEAD(server->viewlist);
3180
 
                     view != NULL && view != zoneview;
3181
 
                     view = ISC_LIST_NEXT(view, link))
3182
 
                        ;
3183
 
                if (view == NULL)
3184
 
                        continue;
3185
 
 
3186
 
                addrp = dns_zone_getnotifysrc6(zone);
3187
 
                result = add_listenelt(mctx, list, addrp, ISC_FALSE);
3188
 
                if (result != ISC_R_SUCCESS)
3189
 
                        goto fail;
3190
 
 
3191
 
                addrp = dns_zone_getxfrsource6(zone);
3192
 
                result = add_listenelt(mctx, list, addrp, ISC_FALSE);
3193
 
                if (result != ISC_R_SUCCESS)
3194
 
                        goto fail;
3195
 
        }
3196
 
 
3197
 
        ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
3198
 
 
3199
 
 clean:
3200
 
        ns_listenlist_detach(&list);
3201
 
        return;
3202
 
 
3203
 
 fail:
3204
 
        /*
3205
 
         * Even when we failed the procedure, most of other interfaces
3206
 
         * should work correctly.  We therefore just warn it.
3207
 
         */
3208
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3209
 
                      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3210
 
                      "could not adjust the listen-on list; "
3211
 
                      "some interfaces may not work");
3212
 
        goto clean;
3213
 
}
3214
 
 
3215
 
/*
3216
 
 * This event callback is invoked to do periodic network
3217
 
 * interface scanning.
3218
 
 */
3219
 
static void
3220
 
interface_timer_tick(isc_task_t *task, isc_event_t *event) {
3221
 
        isc_result_t result;
3222
 
        ns_server_t *server = (ns_server_t *) event->ev_arg;
3223
 
        INSIST(task == server->task);
3224
 
        UNUSED(task);
3225
 
        isc_event_free(&event);
3226
 
        /*
3227
 
         * XXX should scan interfaces unlocked and get exclusive access
3228
 
         * only to replace ACLs.
3229
 
         */
3230
 
        result = isc_task_beginexclusive(server->task);
3231
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
3232
 
        scan_interfaces(server, ISC_FALSE);
3233
 
        isc_task_endexclusive(server->task);
3234
 
}
3235
 
 
3236
 
static void
3237
 
heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
3238
 
        ns_server_t *server = (ns_server_t *) event->ev_arg;
3239
 
        dns_view_t *view;
3240
 
 
3241
 
        UNUSED(task);
3242
 
        isc_event_free(&event);
3243
 
        view = ISC_LIST_HEAD(server->viewlist);
3244
 
        while (view != NULL) {
3245
 
                dns_view_dialup(view);
3246
 
                view = ISC_LIST_NEXT(view, link);
3247
 
        }
3248
 
}
3249
 
 
3250
 
static void
3251
 
pps_timer_tick(isc_task_t *task, isc_event_t *event) {
3252
 
        static unsigned int oldrequests = 0;
3253
 
        unsigned int requests = ns_client_requests;
3254
 
 
3255
 
        UNUSED(task);
3256
 
        isc_event_free(&event);
3257
 
 
3258
 
        /*
3259
 
         * Don't worry about wrapping as the overflow result will be right.
3260
 
         */
3261
 
        dns_pps = (requests - oldrequests) / 1200;
3262
 
        oldrequests = requests;
3263
 
}
3264
 
 
3265
 
/*
3266
 
 * Replace the current value of '*field', a dynamically allocated
3267
 
 * string or NULL, with a dynamically allocated copy of the
3268
 
 * null-terminated string pointed to by 'value', or NULL.
3269
 
 */
3270
 
static isc_result_t
3271
 
setstring(ns_server_t *server, char **field, const char *value) {
3272
 
        char *copy;
3273
 
 
3274
 
        if (value != NULL) {
3275
 
                copy = isc_mem_strdup(server->mctx, value);
3276
 
                if (copy == NULL)
3277
 
                        return (ISC_R_NOMEMORY);
3278
 
        } else {
3279
 
                copy = NULL;
3280
 
        }
3281
 
 
3282
 
        if (*field != NULL)
3283
 
                isc_mem_free(server->mctx, *field);
3284
 
 
3285
 
        *field = copy;
3286
 
        return (ISC_R_SUCCESS);
3287
 
}
3288
 
 
3289
 
/*
3290
 
 * Replace the current value of '*field', a dynamically allocated
3291
 
 * string or NULL, with another dynamically allocated string
3292
 
 * or NULL if whether 'obj' is a string or void value, respectively.
3293
 
 */
3294
 
static isc_result_t
3295
 
setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) {
3296
 
        if (cfg_obj_isvoid(obj))
3297
 
                return (setstring(server, field, NULL));
3298
 
        else
3299
 
                return (setstring(server, field, cfg_obj_asstring(obj)));
3300
 
}
3301
 
 
3302
 
static void
3303
 
set_limit(const cfg_obj_t **maps, const char *configname,
3304
 
          const char *description, isc_resource_t resourceid,
3305
 
          isc_resourcevalue_t defaultvalue)
3306
 
{
3307
 
        const cfg_obj_t *obj = NULL;
3308
 
        const char *resource;
3309
 
        isc_resourcevalue_t value;
3310
 
        isc_result_t result;
3311
 
 
3312
 
        if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
3313
 
                return;
3314
 
 
3315
 
        if (cfg_obj_isstring(obj)) {
3316
 
                resource = cfg_obj_asstring(obj);
3317
 
                if (strcasecmp(resource, "unlimited") == 0)
3318
 
                        value = ISC_RESOURCE_UNLIMITED;
3319
 
                else {
3320
 
                        INSIST(strcasecmp(resource, "default") == 0);
3321
 
                        value = defaultvalue;
3322
 
                }
3323
 
        } else
3324
 
                value = cfg_obj_asuint64(obj);
3325
 
 
3326
 
        result = isc_resource_setlimit(resourceid, value);
3327
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3328
 
                      result == ISC_R_SUCCESS ?
3329
 
                        ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
3330
 
                      "set maximum %s to %" ISC_PRINT_QUADFORMAT "u: %s",
3331
 
                      description, value, isc_result_totext(result));
3332
 
}
3333
 
 
3334
 
#define SETLIMIT(cfgvar, resource, description) \
3335
 
        set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
3336
 
                  ns_g_init ## resource)
3337
 
 
3338
 
static void
3339
 
set_limits(const cfg_obj_t **maps) {
3340
 
        SETLIMIT("stacksize", stacksize, "stack size");
3341
 
        SETLIMIT("datasize", datasize, "data size");
3342
 
        SETLIMIT("coresize", coresize, "core size");
3343
 
        SETLIMIT("files", openfiles, "open files");
3344
 
}
3345
 
 
3346
 
static void
3347
 
portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
3348
 
                 isc_boolean_t positive)
3349
 
{
3350
 
        const cfg_listelt_t *element;
3351
 
 
3352
 
        for (element = cfg_list_first(ports);
3353
 
             element != NULL;
3354
 
             element = cfg_list_next(element)) {
3355
 
                const cfg_obj_t *obj = cfg_listelt_value(element);
3356
 
 
3357
 
                if (cfg_obj_isuint32(obj)) {
3358
 
                        in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
3359
 
 
3360
 
                        if (positive)
3361
 
                                isc_portset_add(portset, port);
3362
 
                        else
3363
 
                                isc_portset_remove(portset, port);
3364
 
                } else {
3365
 
                        const cfg_obj_t *obj_loport, *obj_hiport;
3366
 
                        in_port_t loport, hiport;
3367
 
 
3368
 
                        obj_loport = cfg_tuple_get(obj, "loport");
3369
 
                        loport = (in_port_t)cfg_obj_asuint32(obj_loport);
3370
 
                        obj_hiport = cfg_tuple_get(obj, "hiport");
3371
 
                        hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
3372
 
 
3373
 
                        if (positive)
3374
 
                                isc_portset_addrange(portset, loport, hiport);
3375
 
                        else {
3376
 
                                isc_portset_removerange(portset, loport,
3377
 
                                                        hiport);
3378
 
                        }
3379
 
                }
3380
 
        }
3381
 
}
3382
 
 
3383
 
static isc_result_t
3384
 
removed(dns_zone_t *zone, void *uap) {
3385
 
        const char *type;
3386
 
 
3387
 
        if (dns_zone_getview(zone) != uap)
3388
 
                return (ISC_R_SUCCESS);
3389
 
 
3390
 
        switch (dns_zone_gettype(zone)) {
3391
 
        case dns_zone_master:
3392
 
                type = "master";
3393
 
                break;
3394
 
        case dns_zone_slave:
3395
 
                type = "slave";
3396
 
                break;
3397
 
        case dns_zone_stub:
3398
 
                type = "stub";
3399
 
                break;
3400
 
        default:
3401
 
                type = "other";
3402
 
                break;
3403
 
        }
3404
 
        dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type);
3405
 
        return (ISC_R_SUCCESS);
3406
 
}
3407
 
 
3408
 
static void
3409
 
cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) {
3410
 
        if (server->session_keyfile != NULL) {
3411
 
                isc_file_remove(server->session_keyfile);
3412
 
                isc_mem_free(mctx, server->session_keyfile);
3413
 
                server->session_keyfile = NULL;
3414
 
        }
3415
 
 
3416
 
        if (server->session_keyname != NULL) {
3417
 
                if (dns_name_dynamic(server->session_keyname))
3418
 
                        dns_name_free(server->session_keyname, mctx);
3419
 
                isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t));
3420
 
                server->session_keyname = NULL;
3421
 
        }
3422
 
 
3423
 
        if (server->sessionkey != NULL)
3424
 
                dns_tsigkey_detach(&server->sessionkey);
3425
 
 
3426
 
        server->session_keyalg = DST_ALG_UNKNOWN;
3427
 
        server->session_keybits = 0;
3428
 
}
3429
 
 
3430
 
static isc_result_t
3431
 
generate_session_key(const char *filename, const char *keynamestr,
3432
 
                     dns_name_t *keyname, const char *algstr,
3433
 
                     dns_name_t *algname, unsigned int algtype,
3434
 
                     isc_uint16_t bits, isc_mem_t *mctx,
3435
 
                     dns_tsigkey_t **tsigkeyp)
3436
 
{
3437
 
        isc_result_t result = ISC_R_SUCCESS;
3438
 
        dst_key_t *key = NULL;
3439
 
        isc_buffer_t key_txtbuffer;
3440
 
        isc_buffer_t key_rawbuffer;
3441
 
        char key_txtsecret[256];
3442
 
        char key_rawsecret[64];
3443
 
        isc_region_t key_rawregion;
3444
 
        isc_stdtime_t now;
3445
 
        dns_tsigkey_t *tsigkey = NULL;
3446
 
        FILE *fp = NULL;
3447
 
 
3448
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3449
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3450
 
                      "generating session key for dynamic DNS");
3451
 
 
3452
 
        /* generate key */
3453
 
        result = dst_key_generate(keyname, algtype, bits, 1, 0,
3454
 
                                  DNS_KEYPROTO_ANY, dns_rdataclass_in,
3455
 
                                  mctx, &key);
3456
 
        if (result != ISC_R_SUCCESS)
3457
 
                return (result);
3458
 
 
3459
 
        /*
3460
 
         * Dump the key to the buffer for later use.  Should be done before
3461
 
         * we transfer the ownership of key to tsigkey.
3462
 
         */
3463
 
        isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
3464
 
        CHECK(dst_key_tobuffer(key, &key_rawbuffer));
3465
 
 
3466
 
        isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
3467
 
        isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
3468
 
        CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer));
3469
 
 
3470
 
        /* Store the key in tsigkey. */
3471
 
        isc_stdtime_get(&now);
3472
 
        CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key,
3473
 
                                        ISC_FALSE, NULL, now, now, mctx, NULL,
3474
 
                                        &tsigkey));
3475
 
        key = NULL;             /* ownership of key has been transferred */
3476
 
 
3477
 
        /* Dump the key to the key file. */
3478
 
        fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE);
3479
 
        if (fp == NULL) {
3480
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3481
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3482
 
                              "could not create %s", filename);
3483
 
                result = ISC_R_NOPERM;
3484
 
                goto cleanup;
3485
 
        }
3486
 
 
3487
 
        fprintf(fp, "key \"%s\" {\n"
3488
 
                "\talgorithm %s;\n"
3489
 
                "\tsecret \"%.*s\";\n};\n", keynamestr, algstr,
3490
 
                (int) isc_buffer_usedlength(&key_txtbuffer),
3491
 
                (char*) isc_buffer_base(&key_txtbuffer));
3492
 
 
3493
 
        RUNTIME_CHECK(isc_stdio_flush(fp) == ISC_R_SUCCESS);
3494
 
        RUNTIME_CHECK(isc_stdio_close(fp) == ISC_R_SUCCESS);
3495
 
 
3496
 
        *tsigkeyp = tsigkey;
3497
 
 
3498
 
        return (ISC_R_SUCCESS);
3499
 
 
3500
 
  cleanup:
3501
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3502
 
                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
3503
 
                      "failed to generate session key "
3504
 
                      "for dynamic DNS: %s", isc_result_totext(result));
3505
 
        if (tsigkey != NULL)
3506
 
                dns_tsigkey_detach(&tsigkey);
3507
 
        if (key != NULL)
3508
 
                dst_key_free(&key);
3509
 
 
3510
 
        return (result);
3511
 
}
3512
 
 
3513
 
static isc_result_t
3514
 
configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
3515
 
                      isc_mem_t *mctx)
3516
 
{
3517
 
        const char *keyfile, *keynamestr, *algstr;
3518
 
        unsigned int algtype;
3519
 
        dns_fixedname_t fname;
3520
 
        dns_name_t *keyname, *algname;
3521
 
        isc_buffer_t buffer;
3522
 
        isc_uint16_t bits;
3523
 
        const cfg_obj_t *obj;
3524
 
        isc_boolean_t need_deleteold = ISC_FALSE;
3525
 
        isc_boolean_t need_createnew = ISC_FALSE;
3526
 
        isc_result_t result;
3527
 
 
3528
 
        obj = NULL;
3529
 
        result = ns_config_get(maps, "session-keyfile", &obj);
3530
 
        if (result == ISC_R_SUCCESS) {
3531
 
                if (cfg_obj_isvoid(obj))
3532
 
                        keyfile = NULL; /* disable it */
3533
 
                else
3534
 
                        keyfile = cfg_obj_asstring(obj);
3535
 
        } else
3536
 
                keyfile = ns_g_defaultsessionkeyfile;
3537
 
 
3538
 
        obj = NULL;
3539
 
        result = ns_config_get(maps, "session-keyname", &obj);
3540
 
        INSIST(result == ISC_R_SUCCESS);
3541
 
        keynamestr = cfg_obj_asstring(obj);
3542
 
        dns_fixedname_init(&fname);
3543
 
        isc_buffer_init(&buffer, keynamestr, strlen(keynamestr));
3544
 
        isc_buffer_add(&buffer, strlen(keynamestr));
3545
 
        keyname = dns_fixedname_name(&fname);
3546
 
        result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL);
3547
 
        if (result != ISC_R_SUCCESS)
3548
 
                return (result);
3549
 
 
3550
 
        obj = NULL;
3551
 
        result = ns_config_get(maps, "session-keyalg", &obj);
3552
 
        INSIST(result == ISC_R_SUCCESS);
3553
 
        algstr = cfg_obj_asstring(obj);
3554
 
        algname = NULL;
3555
 
        result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits);
3556
 
        if (result != ISC_R_SUCCESS) {
3557
 
                const char *s = " (keeping current key)";
3558
 
 
3559
 
                cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: "
3560
 
                            "unsupported or unknown algorithm '%s'%s",
3561
 
                            algstr,
3562
 
                            server->session_keyfile != NULL ? s : "");
3563
 
                return (result);
3564
 
        }
3565
 
 
3566
 
        /* See if we need to (re)generate a new key. */
3567
 
        if (keyfile == NULL) {
3568
 
                if (server->session_keyfile != NULL)
3569
 
                        need_deleteold = ISC_TRUE;
3570
 
        } else if (server->session_keyfile == NULL)
3571
 
                need_createnew = ISC_TRUE;
3572
 
        else if (strcmp(keyfile, server->session_keyfile) != 0 ||
3573
 
                 !dns_name_equal(server->session_keyname, keyname) ||
3574
 
                 server->session_keyalg != algtype ||
3575
 
                 server->session_keybits != bits) {
3576
 
                need_deleteold = ISC_TRUE;
3577
 
                need_createnew = ISC_TRUE;
3578
 
        }
3579
 
 
3580
 
        if (need_deleteold) {
3581
 
                INSIST(server->session_keyfile != NULL);
3582
 
                INSIST(server->session_keyname != NULL);
3583
 
                INSIST(server->sessionkey != NULL);
3584
 
 
3585
 
                cleanup_session_key(server, mctx);
3586
 
        }
3587
 
 
3588
 
        if (need_createnew) {
3589
 
                INSIST(server->sessionkey == NULL);
3590
 
                INSIST(server->session_keyfile == NULL);
3591
 
                INSIST(server->session_keyname == NULL);
3592
 
                INSIST(server->session_keyalg == DST_ALG_UNKNOWN);
3593
 
                INSIST(server->session_keybits == 0);
3594
 
 
3595
 
                server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t));
3596
 
                if (server->session_keyname == NULL)
3597
 
                        goto cleanup;
3598
 
                dns_name_init(server->session_keyname, NULL);
3599
 
                CHECK(dns_name_dup(keyname, mctx, server->session_keyname));
3600
 
 
3601
 
                server->session_keyfile = isc_mem_strdup(mctx, keyfile);
3602
 
                if (server->session_keyfile == NULL)
3603
 
                        goto cleanup;
3604
 
 
3605
 
                server->session_keyalg = algtype;
3606
 
                server->session_keybits = bits;
3607
 
 
3608
 
                CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr,
3609
 
                                           algname, algtype, bits, mctx,
3610
 
                                           &server->sessionkey));
3611
 
        }
3612
 
 
3613
 
        return (result);
3614
 
 
3615
 
  cleanup:
3616
 
        cleanup_session_key(server, mctx);
3617
 
        return (result);
3618
 
}
3619
 
 
3620
 
static isc_result_t
3621
 
load_configuration(const char *filename, ns_server_t *server,
3622
 
                   isc_boolean_t first_time)
3623
 
{
3624
 
        cfg_aclconfctx_t aclconfctx;
3625
 
        cfg_obj_t *config = NULL, *bindkeys = NULL;
3626
 
        cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL;
3627
 
        const cfg_listelt_t *element;
3628
 
        const cfg_obj_t *builtin_views;
3629
 
        const cfg_obj_t *maps[3];
3630
 
        const cfg_obj_t *obj;
3631
 
        const cfg_obj_t *options;
3632
 
        const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
3633
 
        const cfg_obj_t *views;
3634
 
        dns_view_t *view = NULL;
3635
 
        dns_view_t *view_next;
3636
 
        dns_viewlist_t tmpviewlist;
3637
 
        dns_viewlist_t viewlist, builtin_viewlist;
3638
 
        in_port_t listen_port, udpport_low, udpport_high;
3639
 
        int i;
3640
 
        isc_interval_t interval;
3641
 
        isc_portset_t *v4portset = NULL;
3642
 
        isc_portset_t *v6portset = NULL;
3643
 
        isc_resourcevalue_t nfiles;
3644
 
        isc_result_t result;
3645
 
        isc_uint32_t heartbeat_interval;
3646
 
        isc_uint32_t interface_interval;
3647
 
        isc_uint32_t reserved;
3648
 
        isc_uint32_t udpsize;
3649
 
        ns_cachelist_t cachelist, tmpcachelist;
3650
 
        unsigned int maxsocks;
3651
 
        ns_cache_t *nsc;
3652
 
 
3653
 
        cfg_aclconfctx_init(&aclconfctx);
3654
 
        ISC_LIST_INIT(viewlist);
3655
 
        ISC_LIST_INIT(builtin_viewlist);
3656
 
        ISC_LIST_INIT(cachelist);
3657
 
 
3658
 
        /* Ensure exclusive access to configuration data. */
3659
 
        result = isc_task_beginexclusive(server->task);
3660
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
3661
 
 
3662
 
        /*
3663
 
         * Parse the global default pseudo-config file.
3664
 
         */
3665
 
        if (first_time) {
3666
 
                CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
3667
 
                RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
3668
 
                                          &ns_g_defaults) == ISC_R_SUCCESS);
3669
 
        }
3670
 
 
3671
 
        /*
3672
 
         * Parse the configuration file using the new config code.
3673
 
         */
3674
 
        result = ISC_R_FAILURE;
3675
 
        config = NULL;
3676
 
 
3677
 
        /*
3678
 
         * Unless this is lwresd with the -C option, parse the config file.
3679
 
         */
3680
 
        if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
3681
 
                isc_log_write(ns_g_lctx,
3682
 
                              NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3683
 
                              ISC_LOG_INFO, "loading configuration from '%s'",
3684
 
                              filename);
3685
 
                CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
3686
 
                cfg_parser_setcallback(conf_parser, directory_callback, NULL);
3687
 
                result = cfg_parse_file(conf_parser, filename,
3688
 
                                        &cfg_type_namedconf, &config);
3689
 
        }
3690
 
 
3691
 
        /*
3692
 
         * If this is lwresd with the -C option, or lwresd with no -C or -c
3693
 
         * option where the above parsing failed, parse resolv.conf.
3694
 
         */
3695
 
        if (ns_g_lwresdonly &&
3696
 
            (lwresd_g_useresolvconf ||
3697
 
             (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
3698
 
        {
3699
 
                isc_log_write(ns_g_lctx,
3700
 
                              NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
3701
 
                              ISC_LOG_INFO, "loading configuration from '%s'",
3702
 
                              lwresd_g_resolvconffile);
3703
 
                if (conf_parser != NULL)
3704
 
                        cfg_parser_destroy(&conf_parser);
3705
 
                CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
3706
 
                result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser,
3707
 
                                                    &config);
3708
 
        }
3709
 
        CHECK(result);
3710
 
 
3711
 
        /*
3712
 
         * Check the validity of the configuration.
3713
 
         */
3714
 
        CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
3715
 
 
3716
 
        /*
3717
 
         * Fill in the maps array, used for resolving defaults.
3718
 
         */
3719
 
        i = 0;
3720
 
        options = NULL;
3721
 
        result = cfg_map_get(config, "options", &options);
3722
 
        if (result == ISC_R_SUCCESS)
3723
 
                maps[i++] = options;
3724
 
        maps[i++] = ns_g_defaults;
3725
 
        maps[i++] = NULL;
3726
 
 
3727
 
        /*
3728
 
         * If bind.keys exists, load it.  If "dnssec-lookaside auto"
3729
 
         * is turned on, the keys found there will be used as default
3730
 
         * trust anchors.
3731
 
         */
3732
 
        obj = NULL;
3733
 
        result = ns_config_get(maps, "bindkeys-file", &obj);
3734
 
        INSIST(result == ISC_R_SUCCESS);
3735
 
        CHECKM(setstring(server, &server->bindkeysfile,
3736
 
               cfg_obj_asstring(obj)), "strdup");
3737
 
 
3738
 
        if (access(server->bindkeysfile, R_OK) == 0) {
3739
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3740
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3741
 
                              "reading built-in trusted "
3742
 
                              "keys from file '%s'", server->bindkeysfile);
3743
 
 
3744
 
                CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx,
3745
 
                                        &bindkeys_parser));
3746
 
 
3747
 
                result = cfg_parse_file(bindkeys_parser, server->bindkeysfile,
3748
 
                                        &cfg_type_bindkeys, &bindkeys);
3749
 
                CHECK(result);
3750
 
        }
3751
 
 
3752
 
        /*
3753
 
         * Set process limits, which (usually) needs to be done as root.
3754
 
         */
3755
 
        set_limits(maps);
3756
 
 
3757
 
        /*
3758
 
         * Check if max number of open sockets that the system allows is
3759
 
         * sufficiently large.  Failing this condition is not necessarily fatal,
3760
 
         * but may cause subsequent runtime failures for a busy recursive
3761
 
         * server.
3762
 
         */
3763
 
        result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);
3764
 
        if (result != ISC_R_SUCCESS)
3765
 
                maxsocks = 0;
3766
 
        result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
3767
 
        if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
3768
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3769
 
                              NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3770
 
                              "max open files (%" ISC_PRINT_QUADFORMAT "u)"
3771
 
                              " is smaller than max sockets (%u)",
3772
 
                              nfiles, maxsocks);
3773
 
        }
3774
 
 
3775
 
        /*
3776
 
         * Set the number of socket reserved for TCP, stdio etc.
3777
 
         */
3778
 
        obj = NULL;
3779
 
        result = ns_config_get(maps, "reserved-sockets", &obj);
3780
 
        INSIST(result == ISC_R_SUCCESS);
3781
 
        reserved = cfg_obj_asuint32(obj);
3782
 
        if (maxsocks != 0) {
3783
 
                if (maxsocks < 128U)                    /* Prevent underflow. */
3784
 
                        reserved = 0;
3785
 
                else if (reserved > maxsocks - 128U)    /* Minimum UDP space. */
3786
 
                        reserved = maxsocks - 128;
3787
 
        }
3788
 
        /* Minimum TCP/stdio space. */
3789
 
        if (reserved < 128U)
3790
 
                reserved = 128;
3791
 
        if (reserved + 128U > maxsocks && maxsocks != 0) {
3792
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3793
 
                              NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
3794
 
                              "less than 128 UDP sockets available after "
3795
 
                              "applying 'reserved-sockets' and 'maxsockets'");
3796
 
        }
3797
 
        isc__socketmgr_setreserved(ns_g_socketmgr, reserved);
3798
 
 
3799
 
        /*
3800
 
         * Configure various server options.
3801
 
         */
3802
 
        configure_server_quota(maps, "transfers-out", &server->xfroutquota);
3803
 
        configure_server_quota(maps, "tcp-clients", &server->tcpquota);
3804
 
        configure_server_quota(maps, "recursive-clients",
3805
 
                               &server->recursionquota);
3806
 
        if (server->recursionquota.max > 1000)
3807
 
                isc_quota_soft(&server->recursionquota,
3808
 
                               server->recursionquota.max - 100);
3809
 
        else
3810
 
                isc_quota_soft(&server->recursionquota, 0);
3811
 
 
3812
 
        CHECK(configure_view_acl(NULL, config, "blackhole", NULL, &aclconfctx,
3813
 
                                 ns_g_mctx, &server->blackholeacl));
3814
 
        if (server->blackholeacl != NULL)
3815
 
                dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
3816
 
                                             server->blackholeacl);
3817
 
 
3818
 
        obj = NULL;
3819
 
        result = ns_config_get(maps, "match-mapped-addresses", &obj);
3820
 
        INSIST(result == ISC_R_SUCCESS);
3821
 
        server->aclenv.match_mapped = cfg_obj_asboolean(obj);
3822
 
 
3823
 
        CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),
3824
 
               "configuring statistics server(s)");
3825
 
 
3826
 
        /*
3827
 
         * Configure sets of UDP query source ports.
3828
 
         */
3829
 
        CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
3830
 
               "creating UDP port set");
3831
 
        CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
3832
 
               "creating UDP port set");
3833
 
 
3834
 
        usev4ports = NULL;
3835
 
        usev6ports = NULL;
3836
 
        avoidv4ports = NULL;
3837
 
        avoidv6ports = NULL;
3838
 
 
3839
 
        (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
3840
 
        if (usev4ports != NULL)
3841
 
                portset_fromconf(v4portset, usev4ports, ISC_TRUE);
3842
 
        else {
3843
 
                CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
3844
 
                                               &udpport_high),
3845
 
                       "get the default UDP/IPv4 port range");
3846
 
                if (udpport_low == udpport_high)
3847
 
                        isc_portset_add(v4portset, udpport_low);
3848
 
                else {
3849
 
                        isc_portset_addrange(v4portset, udpport_low,
3850
 
                                             udpport_high);
3851
 
                }
3852
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3853
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3854
 
                              "using default UDP/IPv4 port range: [%d, %d]",
3855
 
                              udpport_low, udpport_high);
3856
 
        }
3857
 
        (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
3858
 
        if (avoidv4ports != NULL)
3859
 
                portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
3860
 
 
3861
 
        (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
3862
 
        if (usev6ports != NULL)
3863
 
                portset_fromconf(v6portset, usev6ports, ISC_TRUE);
3864
 
        else {
3865
 
                CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
3866
 
                                               &udpport_high),
3867
 
                       "get the default UDP/IPv6 port range");
3868
 
                if (udpport_low == udpport_high)
3869
 
                        isc_portset_add(v6portset, udpport_low);
3870
 
                else {
3871
 
                        isc_portset_addrange(v6portset, udpport_low,
3872
 
                                             udpport_high);
3873
 
                }
3874
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
3875
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
3876
 
                              "using default UDP/IPv6 port range: [%d, %d]",
3877
 
                              udpport_low, udpport_high);
3878
 
        }
3879
 
        (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
3880
 
        if (avoidv6ports != NULL)
3881
 
                portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
3882
 
 
3883
 
        dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
3884
 
 
3885
 
        /*
3886
 
         * Set the EDNS UDP size when we don't match a view.
3887
 
         */
3888
 
        obj = NULL;
3889
 
        result = ns_config_get(maps, "edns-udp-size", &obj);
3890
 
        INSIST(result == ISC_R_SUCCESS);
3891
 
        udpsize = cfg_obj_asuint32(obj);
3892
 
        if (udpsize < 512)
3893
 
                udpsize = 512;
3894
 
        if (udpsize > 4096)
3895
 
                udpsize = 4096;
3896
 
        ns_g_udpsize = (isc_uint16_t)udpsize;
3897
 
 
3898
 
        /*
3899
 
         * Configure the zone manager.
3900
 
         */
3901
 
        obj = NULL;
3902
 
        result = ns_config_get(maps, "transfers-in", &obj);
3903
 
        INSIST(result == ISC_R_SUCCESS);
3904
 
        dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
3905
 
 
3906
 
        obj = NULL;
3907
 
        result = ns_config_get(maps, "transfers-per-ns", &obj);
3908
 
        INSIST(result == ISC_R_SUCCESS);
3909
 
        dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
3910
 
 
3911
 
        obj = NULL;
3912
 
        result = ns_config_get(maps, "serial-query-rate", &obj);
3913
 
        INSIST(result == ISC_R_SUCCESS);
3914
 
        dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
3915
 
 
3916
 
        /*
3917
 
         * Determine which port to use for listening for incoming connections.
3918
 
         */
3919
 
        if (ns_g_port != 0)
3920
 
                listen_port = ns_g_port;
3921
 
        else
3922
 
                CHECKM(ns_config_getport(config, &listen_port), "port");
3923
 
 
3924
 
        /*
3925
 
         * Find the listen queue depth.
3926
 
         */
3927
 
        obj = NULL;
3928
 
        result = ns_config_get(maps, "tcp-listen-queue", &obj);
3929
 
        INSIST(result == ISC_R_SUCCESS);
3930
 
        ns_g_listen = cfg_obj_asuint32(obj);
3931
 
        if (ns_g_listen < 3)
3932
 
                ns_g_listen = 3;
3933
 
 
3934
 
        /*
3935
 
         * Configure the interface manager according to the "listen-on"
3936
 
         * statement.
3937
 
         */
3938
 
        {
3939
 
                const cfg_obj_t *clistenon = NULL;
3940
 
                ns_listenlist_t *listenon = NULL;
3941
 
 
3942
 
                clistenon = NULL;
3943
 
                /*
3944
 
                 * Even though listen-on is present in the default
3945
 
                 * configuration, we can't use it here, since it isn't
3946
 
                 * used if we're in lwresd mode.  This way is easier.
3947
 
                 */
3948
 
                if (options != NULL)
3949
 
                        (void)cfg_map_get(options, "listen-on", &clistenon);
3950
 
                if (clistenon != NULL) {
3951
 
                        result = ns_listenlist_fromconfig(clistenon,
3952
 
                                                          config,
3953
 
                                                          &aclconfctx,
3954
 
                                                          ns_g_mctx,
3955
 
                                                          &listenon);
3956
 
                } else if (!ns_g_lwresdonly) {
3957
 
                        /*
3958
 
                         * Not specified, use default.
3959
 
                         */
3960
 
                        CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
3961
 
                                                    ISC_TRUE, &listenon));
3962
 
                }
3963
 
                if (listenon != NULL) {
3964
 
                        ns_interfacemgr_setlistenon4(server->interfacemgr,
3965
 
                                                     listenon);
3966
 
                        ns_listenlist_detach(&listenon);
3967
 
                }
3968
 
        }
3969
 
        /*
3970
 
         * Ditto for IPv6.
3971
 
         */
3972
 
        {
3973
 
                const cfg_obj_t *clistenon = NULL;
3974
 
                ns_listenlist_t *listenon = NULL;
3975
 
 
3976
 
                if (options != NULL)
3977
 
                        (void)cfg_map_get(options, "listen-on-v6", &clistenon);
3978
 
                if (clistenon != NULL) {
3979
 
                        result = ns_listenlist_fromconfig(clistenon,
3980
 
                                                          config,
3981
 
                                                          &aclconfctx,
3982
 
                                                          ns_g_mctx,
3983
 
                                                          &listenon);
3984
 
                } else if (!ns_g_lwresdonly) {
3985
 
                        isc_boolean_t enable;
3986
 
                        /*
3987
 
                         * Not specified, use default.
3988
 
                         */
3989
 
                        enable = ISC_TF(isc_net_probeipv4() != ISC_R_SUCCESS);
3990
 
                        CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
3991
 
                                                    enable, &listenon));
3992
 
                }
3993
 
                if (listenon != NULL) {
3994
 
                        ns_interfacemgr_setlistenon6(server->interfacemgr,
3995
 
                                                     listenon);
3996
 
                        ns_listenlist_detach(&listenon);
3997
 
                }
3998
 
        }
3999
 
 
4000
 
        /*
4001
 
         * Rescan the interface list to pick up changes in the
4002
 
         * listen-on option.  It's important that we do this before we try
4003
 
         * to configure the query source, since the dispatcher we use might
4004
 
         * be shared with an interface.
4005
 
         */
4006
 
        scan_interfaces(server, ISC_TRUE);
4007
 
 
4008
 
        /*
4009
 
         * Arrange for further interface scanning to occur periodically
4010
 
         * as specified by the "interface-interval" option.
4011
 
         */
4012
 
        obj = NULL;
4013
 
        result = ns_config_get(maps, "interface-interval", &obj);
4014
 
        INSIST(result == ISC_R_SUCCESS);
4015
 
        interface_interval = cfg_obj_asuint32(obj) * 60;
4016
 
        if (interface_interval == 0) {
4017
 
                CHECK(isc_timer_reset(server->interface_timer,
4018
 
                                      isc_timertype_inactive,
4019
 
                                      NULL, NULL, ISC_TRUE));
4020
 
        } else if (server->interface_interval != interface_interval) {
4021
 
                isc_interval_set(&interval, interface_interval, 0);
4022
 
                CHECK(isc_timer_reset(server->interface_timer,
4023
 
                                      isc_timertype_ticker,
4024
 
                                      NULL, &interval, ISC_FALSE));
4025
 
        }
4026
 
        server->interface_interval = interface_interval;
4027
 
 
4028
 
        /*
4029
 
         * Configure the dialup heartbeat timer.
4030
 
         */
4031
 
        obj = NULL;
4032
 
        result = ns_config_get(maps, "heartbeat-interval", &obj);
4033
 
        INSIST(result == ISC_R_SUCCESS);
4034
 
        heartbeat_interval = cfg_obj_asuint32(obj) * 60;
4035
 
        if (heartbeat_interval == 0) {
4036
 
                CHECK(isc_timer_reset(server->heartbeat_timer,
4037
 
                                      isc_timertype_inactive,
4038
 
                                      NULL, NULL, ISC_TRUE));
4039
 
        } else if (server->heartbeat_interval != heartbeat_interval) {
4040
 
                isc_interval_set(&interval, heartbeat_interval, 0);
4041
 
                CHECK(isc_timer_reset(server->heartbeat_timer,
4042
 
                                      isc_timertype_ticker,
4043
 
                                      NULL, &interval, ISC_FALSE));
4044
 
        }
4045
 
        server->heartbeat_interval = heartbeat_interval;
4046
 
 
4047
 
        isc_interval_set(&interval, 1200, 0);
4048
 
        CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
4049
 
                              &interval, ISC_FALSE));
4050
 
 
4051
 
        /*
4052
 
         * Write the PID file.
4053
 
         */
4054
 
        obj = NULL;
4055
 
        if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
4056
 
                if (cfg_obj_isvoid(obj))
4057
 
                        ns_os_writepidfile(NULL, first_time);
4058
 
                else
4059
 
                        ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
4060
 
        else if (ns_g_lwresdonly)
4061
 
                ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
4062
 
        else
4063
 
                ns_os_writepidfile(ns_g_defaultpidfile, first_time);
4064
 
 
4065
 
        /*
4066
 
         * Configure the server-wide session key.  This must be done before
4067
 
         * configure views because zone configuration may need to know
4068
 
         * session-keyname.
4069
 
         *
4070
 
         * Failure of session key generation isn't fatal at this time; if it
4071
 
         * turns out that a session key is really needed but doesn't exist,
4072
 
         * we'll treat it as a fatal error then.
4073
 
         */
4074
 
        (void)configure_session_key(maps, server, ns_g_mctx);
4075
 
 
4076
 
        /*
4077
 
         * Configure and freeze all explicit views.  Explicit
4078
 
         * views that have zones were already created at parsing
4079
 
         * time, but views with no zones must be created here.
4080
 
         */
4081
 
        views = NULL;
4082
 
        (void)cfg_map_get(config, "view", &views);
4083
 
        for (element = cfg_list_first(views);
4084
 
             element != NULL;
4085
 
             element = cfg_list_next(element))
4086
 
        {
4087
 
                const cfg_obj_t *vconfig = cfg_listelt_value(element);
4088
 
                view = NULL;
4089
 
 
4090
 
                CHECK(create_view(vconfig, &viewlist, &view));
4091
 
                INSIST(view != NULL);
4092
 
                CHECK(configure_view(view, config, vconfig,
4093
 
                                     &cachelist, bindkeys,
4094
 
                                     ns_g_mctx, &aclconfctx, ISC_TRUE));
4095
 
                dns_view_freeze(view);
4096
 
                dns_view_detach(&view);
4097
 
        }
4098
 
 
4099
 
        /*
4100
 
         * Make sure we have a default view if and only if there
4101
 
         * were no explicit views.
4102
 
         */
4103
 
        if (views == NULL) {
4104
 
                /*
4105
 
                 * No explicit views; there ought to be a default view.
4106
 
                 * There may already be one created as a side effect
4107
 
                 * of zone statements, or we may have to create one.
4108
 
                 * In either case, we need to configure and freeze it.
4109
 
                 */
4110
 
                CHECK(create_view(NULL, &viewlist, &view));
4111
 
                CHECK(configure_view(view, config, NULL,
4112
 
                                     &cachelist, bindkeys,
4113
 
                                     ns_g_mctx, &aclconfctx, ISC_TRUE));
4114
 
                dns_view_freeze(view);
4115
 
                dns_view_detach(&view);
4116
 
        }
4117
 
 
4118
 
        /*
4119
 
         * Create (or recreate) the built-in views.
4120
 
         */
4121
 
        builtin_views = NULL;
4122
 
        RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
4123
 
                                  &builtin_views) == ISC_R_SUCCESS);
4124
 
        for (element = cfg_list_first(builtin_views);
4125
 
             element != NULL;
4126
 
             element = cfg_list_next(element))
4127
 
        {
4128
 
                const cfg_obj_t *vconfig = cfg_listelt_value(element);
4129
 
 
4130
 
                CHECK(create_view(vconfig, &builtin_viewlist, &view));
4131
 
                CHECK(configure_view(view, config, vconfig,
4132
 
                                     &cachelist, bindkeys,
4133
 
                                     ns_g_mctx, &aclconfctx, ISC_FALSE));
4134
 
                dns_view_freeze(view);
4135
 
                dns_view_detach(&view);
4136
 
                view = NULL;
4137
 
        }
4138
 
 
4139
 
        /* Now combine the two viewlists into one */
4140
 
        ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
4141
 
 
4142
 
        /* Swap our new view list with the production one. */
4143
 
        tmpviewlist = server->viewlist;
4144
 
        server->viewlist = viewlist;
4145
 
        viewlist = tmpviewlist;
4146
 
 
4147
 
        /* Make the view list available to each of the views */
4148
 
        view = ISC_LIST_HEAD(server->viewlist);
4149
 
        while (view != NULL) {
4150
 
                view->viewlist = &server->viewlist;
4151
 
                view = ISC_LIST_NEXT(view, link);
4152
 
        }
4153
 
 
4154
 
        /* Swap our new cache list with the production one. */
4155
 
        tmpcachelist = server->cachelist;
4156
 
        server->cachelist = cachelist;
4157
 
        cachelist = tmpcachelist;
4158
 
 
4159
 
        /* Load the TKEY information from the configuration. */
4160
 
        if (options != NULL) {
4161
 
                dns_tkeyctx_t *t = NULL;
4162
 
                CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
4163
 
                                             &t),
4164
 
                       "configuring TKEY");
4165
 
                if (server->tkeyctx != NULL)
4166
 
                        dns_tkeyctx_destroy(&server->tkeyctx);
4167
 
                server->tkeyctx = t;
4168
 
        }
4169
 
 
4170
 
        /*
4171
 
         * Bind the control port(s).
4172
 
         */
4173
 
        CHECKM(ns_controls_configure(ns_g_server->controls, config,
4174
 
                                     &aclconfctx),
4175
 
               "binding control channel(s)");
4176
 
 
4177
 
        /*
4178
 
         * Bind the lwresd port(s).
4179
 
         */
4180
 
        CHECKM(ns_lwresd_configure(ns_g_mctx, config),
4181
 
               "binding lightweight resolver ports");
4182
 
 
4183
 
        /*
4184
 
         * Open the source of entropy.
4185
 
         */
4186
 
        if (first_time) {
4187
 
                obj = NULL;
4188
 
                result = ns_config_get(maps, "random-device", &obj);
4189
 
                if (result != ISC_R_SUCCESS) {
4190
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4191
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4192
 
                                      "no source of entropy found");
4193
 
                } else {
4194
 
                        const char *randomdev = cfg_obj_asstring(obj);
4195
 
                        result = isc_entropy_createfilesource(ns_g_entropy,
4196
 
                                                              randomdev);
4197
 
                        if (result != ISC_R_SUCCESS)
4198
 
                                isc_log_write(ns_g_lctx,
4199
 
                                              NS_LOGCATEGORY_GENERAL,
4200
 
                                              NS_LOGMODULE_SERVER,
4201
 
                                              ISC_LOG_INFO,
4202
 
                                              "could not open entropy source "
4203
 
                                              "%s: %s",
4204
 
                                              randomdev,
4205
 
                                              isc_result_totext(result));
4206
 
#ifdef PATH_RANDOMDEV
4207
 
                        if (ns_g_fallbackentropy != NULL) {
4208
 
                                if (result != ISC_R_SUCCESS) {
4209
 
                                        isc_log_write(ns_g_lctx,
4210
 
                                                      NS_LOGCATEGORY_GENERAL,
4211
 
                                                      NS_LOGMODULE_SERVER,
4212
 
                                                      ISC_LOG_INFO,
4213
 
                                                      "using pre-chroot entropy source "
4214
 
                                                      "%s",
4215
 
                                                      PATH_RANDOMDEV);
4216
 
                                        isc_entropy_detach(&ns_g_entropy);
4217
 
                                        isc_entropy_attach(ns_g_fallbackentropy,
4218
 
                                                           &ns_g_entropy);
4219
 
                                }
4220
 
                                isc_entropy_detach(&ns_g_fallbackentropy);
4221
 
                        }
4222
 
#endif
4223
 
                }
4224
 
        }
4225
 
 
4226
 
        /*
4227
 
         * Relinquish root privileges.
4228
 
         */
4229
 
        if (first_time)
4230
 
                ns_os_changeuser();
4231
 
 
4232
 
        /*
4233
 
         * Check that the working directory is writable.
4234
 
         */
4235
 
        if (access(".", W_OK) != 0) {
4236
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4237
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4238
 
                              "the working directory is not writable");
4239
 
        }
4240
 
 
4241
 
        /*
4242
 
         * Configure the logging system.
4243
 
         *
4244
 
         * Do this after changing UID to make sure that any log
4245
 
         * files specified in named.conf get created by the
4246
 
         * unprivileged user, not root.
4247
 
         */
4248
 
        if (ns_g_logstderr) {
4249
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4250
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4251
 
                              "ignoring config file logging "
4252
 
                              "statement due to -g option");
4253
 
        } else {
4254
 
                const cfg_obj_t *logobj = NULL;
4255
 
                isc_logconfig_t *logc = NULL;
4256
 
 
4257
 
                CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
4258
 
                       "creating new logging configuration");
4259
 
 
4260
 
                logobj = NULL;
4261
 
                (void)cfg_map_get(config, "logging", &logobj);
4262
 
                if (logobj != NULL) {
4263
 
                        CHECKM(ns_log_configure(logc, logobj),
4264
 
                               "configuring logging");
4265
 
                } else {
4266
 
                        CHECKM(ns_log_setdefaultchannels(logc),
4267
 
                               "setting up default logging channels");
4268
 
                        CHECKM(ns_log_setunmatchedcategory(logc),
4269
 
                               "setting up default 'category unmatched'");
4270
 
                        CHECKM(ns_log_setdefaultcategory(logc),
4271
 
                               "setting up default 'category default'");
4272
 
                }
4273
 
 
4274
 
                result = isc_logconfig_use(ns_g_lctx, logc);
4275
 
                if (result != ISC_R_SUCCESS) {
4276
 
                        isc_logconfig_destroy(&logc);
4277
 
                        CHECKM(result, "installing logging configuration");
4278
 
                }
4279
 
 
4280
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4281
 
                              NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
4282
 
                              "now using logging configuration from "
4283
 
                              "config file");
4284
 
        }
4285
 
 
4286
 
        /*
4287
 
         * Set the default value of the query logging flag depending
4288
 
         * whether a "queries" category has been defined.  This is
4289
 
         * a disgusting hack, but we need to do this for BIND 8
4290
 
         * compatibility.
4291
 
         */
4292
 
        if (first_time) {
4293
 
                const cfg_obj_t *logobj = NULL;
4294
 
                const cfg_obj_t *categories = NULL;
4295
 
 
4296
 
                obj = NULL;
4297
 
                if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
4298
 
                        server->log_queries = cfg_obj_asboolean(obj);
4299
 
                } else {
4300
 
 
4301
 
                        (void)cfg_map_get(config, "logging", &logobj);
4302
 
                        if (logobj != NULL)
4303
 
                                (void)cfg_map_get(logobj, "category",
4304
 
                                                  &categories);
4305
 
                        if (categories != NULL) {
4306
 
                                const cfg_listelt_t *element;
4307
 
                                for (element = cfg_list_first(categories);
4308
 
                                     element != NULL;
4309
 
                                     element = cfg_list_next(element))
4310
 
                                {
4311
 
                                        const cfg_obj_t *catobj;
4312
 
                                        const char *str;
4313
 
 
4314
 
                                        obj = cfg_listelt_value(element);
4315
 
                                        catobj = cfg_tuple_get(obj, "name");
4316
 
                                        str = cfg_obj_asstring(catobj);
4317
 
                                        if (strcasecmp(str, "queries") == 0)
4318
 
                                                server->log_queries = ISC_TRUE;
4319
 
                                }
4320
 
                        }
4321
 
                }
4322
 
        }
4323
 
 
4324
 
 
4325
 
        obj = NULL;
4326
 
        if (options != NULL &&
4327
 
            cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
4328
 
                ns_g_memstatistics = cfg_obj_asboolean(obj);
4329
 
        else
4330
 
                ns_g_memstatistics =
4331
 
                        ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);
4332
 
 
4333
 
        obj = NULL;
4334
 
        if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)
4335
 
                ns_main_setmemstats(cfg_obj_asstring(obj));
4336
 
        else if (ns_g_memstatistics)
4337
 
                ns_main_setmemstats("named.memstats");
4338
 
        else
4339
 
                ns_main_setmemstats(NULL);
4340
 
 
4341
 
        obj = NULL;
4342
 
        result = ns_config_get(maps, "statistics-file", &obj);
4343
 
        INSIST(result == ISC_R_SUCCESS);
4344
 
        CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
4345
 
               "strdup");
4346
 
 
4347
 
        obj = NULL;
4348
 
        result = ns_config_get(maps, "dump-file", &obj);
4349
 
        INSIST(result == ISC_R_SUCCESS);
4350
 
        CHECKM(setstring(server, &server->dumpfile, cfg_obj_asstring(obj)),
4351
 
               "strdup");
4352
 
 
4353
 
        obj = NULL;
4354
 
        result = ns_config_get(maps, "recursing-file", &obj);
4355
 
        INSIST(result == ISC_R_SUCCESS);
4356
 
        CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
4357
 
               "strdup");
4358
 
 
4359
 
        obj = NULL;
4360
 
        result = ns_config_get(maps, "version", &obj);
4361
 
        if (result == ISC_R_SUCCESS) {
4362
 
                CHECKM(setoptstring(server, &server->version, obj), "strdup");
4363
 
                server->version_set = ISC_TRUE;
4364
 
        } else {
4365
 
                server->version_set = ISC_FALSE;
4366
 
        }
4367
 
 
4368
 
        obj = NULL;
4369
 
        result = ns_config_get(maps, "hostname", &obj);
4370
 
        if (result == ISC_R_SUCCESS) {
4371
 
                CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
4372
 
                server->hostname_set = ISC_TRUE;
4373
 
        } else {
4374
 
                server->hostname_set = ISC_FALSE;
4375
 
        }
4376
 
 
4377
 
        obj = NULL;
4378
 
        result = ns_config_get(maps, "server-id", &obj);
4379
 
        server->server_usehostname = ISC_FALSE;
4380
 
        if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
4381
 
                /* The parser translates "hostname" to ISC_TRUE */
4382
 
                server->server_usehostname = cfg_obj_asboolean(obj);
4383
 
                result = setstring(server, &server->server_id, NULL);
4384
 
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
4385
 
        } else if (result == ISC_R_SUCCESS) {
4386
 
                /* Found a quoted string */
4387
 
                CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
4388
 
        } else {
4389
 
                result = setstring(server, &server->server_id, NULL);
4390
 
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
4391
 
        }
4392
 
 
4393
 
        obj = NULL;
4394
 
        result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
4395
 
        if (result == ISC_R_SUCCESS) {
4396
 
                server->flushonshutdown = cfg_obj_asboolean(obj);
4397
 
        } else {
4398
 
                server->flushonshutdown = ISC_FALSE;
4399
 
        }
4400
 
 
4401
 
        result = ISC_R_SUCCESS;
4402
 
 
4403
 
 cleanup:
4404
 
        if (v4portset != NULL)
4405
 
                isc_portset_destroy(ns_g_mctx, &v4portset);
4406
 
 
4407
 
        if (v6portset != NULL)
4408
 
                isc_portset_destroy(ns_g_mctx, &v6portset);
4409
 
 
4410
 
        cfg_aclconfctx_destroy(&aclconfctx);
4411
 
 
4412
 
        if (conf_parser != NULL) {
4413
 
                if (config != NULL)
4414
 
                        cfg_obj_destroy(conf_parser, &config);
4415
 
                cfg_parser_destroy(&conf_parser);
4416
 
        }
4417
 
 
4418
 
        if (bindkeys_parser != NULL) {
4419
 
                if (bindkeys  != NULL)
4420
 
                        cfg_obj_destroy(bindkeys_parser, &bindkeys);
4421
 
                cfg_parser_destroy(&bindkeys_parser);
4422
 
        }
4423
 
 
4424
 
        if (view != NULL)
4425
 
                dns_view_detach(&view);
4426
 
 
4427
 
        /*
4428
 
         * This cleans up either the old production view list
4429
 
         * or our temporary list depending on whether they
4430
 
         * were swapped above or not.
4431
 
         */
4432
 
        for (view = ISC_LIST_HEAD(viewlist);
4433
 
             view != NULL;
4434
 
             view = view_next) {
4435
 
                view_next = ISC_LIST_NEXT(view, link);
4436
 
                ISC_LIST_UNLINK(viewlist, view, link);
4437
 
                if (result == ISC_R_SUCCESS &&
4438
 
                    strcmp(view->name, "_bind") != 0)
4439
 
                        (void)dns_zt_apply(view->zonetable, ISC_FALSE,
4440
 
                                           removed, view);
4441
 
                dns_view_detach(&view);
4442
 
        }
4443
 
 
4444
 
        /* Same cleanup for cache list. */
4445
 
        while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) {
4446
 
                ISC_LIST_UNLINK(cachelist, nsc, link);
4447
 
                dns_cache_detach(&nsc->cache);
4448
 
                isc_mem_put(server->mctx, nsc, sizeof(*nsc));
4449
 
        }
4450
 
 
4451
 
        /*
4452
 
         * Adjust the listening interfaces in accordance with the source
4453
 
         * addresses specified in views and zones.
4454
 
         */
4455
 
        if (isc_net_probeipv6() == ISC_R_SUCCESS)
4456
 
                adjust_interfaces(server, ns_g_mctx);
4457
 
 
4458
 
        /* Relinquish exclusive access to configuration data. */
4459
 
        isc_task_endexclusive(server->task);
4460
 
 
4461
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4462
 
                      ISC_LOG_DEBUG(1), "load_configuration: %s",
4463
 
                      isc_result_totext(result));
4464
 
 
4465
 
        return (result);
4466
 
}
4467
 
 
4468
 
static isc_result_t
4469
 
load_zones(ns_server_t *server, isc_boolean_t stop) {
4470
 
        isc_result_t result;
4471
 
        dns_view_t *view;
4472
 
 
4473
 
        result = isc_task_beginexclusive(server->task);
4474
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4475
 
 
4476
 
        /*
4477
 
         * Load zone data from disk.
4478
 
         */
4479
 
        for (view = ISC_LIST_HEAD(server->viewlist);
4480
 
             view != NULL;
4481
 
             view = ISC_LIST_NEXT(view, link))
4482
 
        {
4483
 
                CHECK(dns_view_load(view, stop));
4484
 
                if (view->managed_keys != NULL)
4485
 
                        CHECK(dns_zone_load(view->managed_keys));
4486
 
        }
4487
 
 
4488
 
        /*
4489
 
         * Force zone maintenance.  Do this after loading
4490
 
         * so that we know when we need to force AXFR of
4491
 
         * slave zones whose master files are missing.
4492
 
         */
4493
 
        CHECK(dns_zonemgr_forcemaint(server->zonemgr));
4494
 
 cleanup:
4495
 
        isc_task_endexclusive(server->task);
4496
 
        return (result);
4497
 
}
4498
 
 
4499
 
static isc_result_t
4500
 
load_new_zones(ns_server_t *server, isc_boolean_t stop) {
4501
 
        isc_result_t result;
4502
 
        dns_view_t *view;
4503
 
 
4504
 
        result = isc_task_beginexclusive(server->task);
4505
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4506
 
 
4507
 
        /*
4508
 
         * Load zone data from disk.
4509
 
         */
4510
 
        for (view = ISC_LIST_HEAD(server->viewlist);
4511
 
             view != NULL;
4512
 
             view = ISC_LIST_NEXT(view, link))
4513
 
        {
4514
 
                CHECK(dns_view_loadnew(view, stop));
4515
 
        }
4516
 
        /*
4517
 
         * Force zone maintenance.  Do this after loading
4518
 
         * so that we know when we need to force AXFR of
4519
 
         * slave zones whose master files are missing.
4520
 
         */
4521
 
        dns_zonemgr_resumexfrs(server->zonemgr);
4522
 
 cleanup:
4523
 
        isc_task_endexclusive(server->task);
4524
 
        return (result);
4525
 
}
4526
 
 
4527
 
static void
4528
 
run_server(isc_task_t *task, isc_event_t *event) {
4529
 
        isc_result_t result;
4530
 
        ns_server_t *server = (ns_server_t *)event->ev_arg;
4531
 
 
4532
 
        INSIST(task == server->task);
4533
 
 
4534
 
        isc_event_free(&event);
4535
 
 
4536
 
        CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
4537
 
                                          &ns_g_dispatchmgr),
4538
 
                   "creating dispatch manager");
4539
 
 
4540
 
        dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
4541
 
 
4542
 
        CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
4543
 
                                          ns_g_socketmgr, ns_g_dispatchmgr,
4544
 
                                          &server->interfacemgr),
4545
 
                   "creating interface manager");
4546
 
 
4547
 
        CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
4548
 
                                    NULL, NULL, server->task,
4549
 
                                    interface_timer_tick,
4550
 
                                    server, &server->interface_timer),
4551
 
                   "creating interface timer");
4552
 
 
4553
 
        CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
4554
 
                                    NULL, NULL, server->task,
4555
 
                                    heartbeat_timer_tick,
4556
 
                                    server, &server->heartbeat_timer),
4557
 
                   "creating heartbeat timer");
4558
 
 
4559
 
        CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
4560
 
                                    NULL, NULL, server->task, pps_timer_tick,
4561
 
                                    server, &server->pps_timer),
4562
 
                   "creating pps timer");
4563
 
 
4564
 
        CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
4565
 
                   "creating default configuration parser");
4566
 
 
4567
 
        if (ns_g_lwresdonly)
4568
 
                CHECKFATAL(load_configuration(lwresd_g_conffile, server,
4569
 
                                              ISC_TRUE),
4570
 
                           "loading configuration");
4571
 
        else
4572
 
                CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
4573
 
                           "loading configuration");
4574
 
 
4575
 
        isc_hash_init();
4576
 
 
4577
 
        CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
4578
 
 
4579
 
        ns_os_started();
4580
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4581
 
                      ISC_LOG_NOTICE, "running");
4582
 
}
4583
 
 
4584
 
void
4585
 
ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
4586
 
 
4587
 
        REQUIRE(NS_SERVER_VALID(server));
4588
 
 
4589
 
        server->flushonshutdown = flush;
4590
 
}
4591
 
 
4592
 
static void
4593
 
shutdown_server(isc_task_t *task, isc_event_t *event) {
4594
 
        isc_result_t result;
4595
 
        dns_view_t *view, *view_next;
4596
 
        ns_server_t *server = (ns_server_t *)event->ev_arg;
4597
 
        isc_boolean_t flush = server->flushonshutdown;
4598
 
        ns_cache_t *nsc;
4599
 
 
4600
 
        UNUSED(task);
4601
 
        INSIST(task == server->task);
4602
 
 
4603
 
        result = isc_task_beginexclusive(server->task);
4604
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4605
 
 
4606
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4607
 
                      ISC_LOG_INFO, "shutting down%s",
4608
 
                      flush ? ": flushing changes" : "");
4609
 
 
4610
 
        ns_statschannels_shutdown(server);
4611
 
        ns_controls_shutdown(server->controls);
4612
 
        end_reserved_dispatches(server, ISC_TRUE);
4613
 
        cleanup_session_key(server, server->mctx);
4614
 
 
4615
 
        cfg_obj_destroy(ns_g_parser, &ns_g_config);
4616
 
        cfg_parser_destroy(&ns_g_parser);
4617
 
 
4618
 
        for (view = ISC_LIST_HEAD(server->viewlist);
4619
 
             view != NULL;
4620
 
             view = view_next) {
4621
 
                view_next = ISC_LIST_NEXT(view, link);
4622
 
                ISC_LIST_UNLINK(server->viewlist, view, link);
4623
 
                if (flush)
4624
 
                        dns_view_flushanddetach(&view);
4625
 
                else
4626
 
                        dns_view_detach(&view);
4627
 
        }
4628
 
 
4629
 
        while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
4630
 
                ISC_LIST_UNLINK(server->cachelist, nsc, link);
4631
 
                dns_cache_detach(&nsc->cache);
4632
 
                isc_mem_put(server->mctx, nsc, sizeof(*nsc));
4633
 
        }
4634
 
 
4635
 
        isc_timer_detach(&server->interface_timer);
4636
 
        isc_timer_detach(&server->heartbeat_timer);
4637
 
        isc_timer_detach(&server->pps_timer);
4638
 
 
4639
 
        ns_interfacemgr_shutdown(server->interfacemgr);
4640
 
        ns_interfacemgr_detach(&server->interfacemgr);
4641
 
 
4642
 
        dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
4643
 
 
4644
 
        dns_zonemgr_shutdown(server->zonemgr);
4645
 
 
4646
 
        if (ns_g_sessionkey != NULL) {
4647
 
                dns_tsigkey_detach(&ns_g_sessionkey);
4648
 
                dns_name_free(&ns_g_sessionkeyname, server->mctx);
4649
 
        }
4650
 
 
4651
 
        if (server->blackholeacl != NULL)
4652
 
                dns_acl_detach(&server->blackholeacl);
4653
 
 
4654
 
        dns_db_detach(&server->in_roothints);
4655
 
 
4656
 
        isc_task_endexclusive(server->task);
4657
 
 
4658
 
        isc_task_detach(&server->task);
4659
 
 
4660
 
        isc_event_free(&event);
4661
 
}
4662
 
 
4663
 
void
4664
 
ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
4665
 
        isc_result_t result;
4666
 
 
4667
 
        ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
4668
 
        if (server == NULL)
4669
 
                fatal("allocating server object", ISC_R_NOMEMORY);
4670
 
 
4671
 
        server->mctx = mctx;
4672
 
        server->task = NULL;
4673
 
 
4674
 
        /* Initialize configuration data with default values. */
4675
 
 
4676
 
        result = isc_quota_init(&server->xfroutquota, 10);
4677
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4678
 
        result = isc_quota_init(&server->tcpquota, 10);
4679
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4680
 
        result = isc_quota_init(&server->recursionquota, 100);
4681
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4682
 
 
4683
 
        result = dns_aclenv_init(mctx, &server->aclenv);
4684
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
4685
 
 
4686
 
        /* Initialize server data structures. */
4687
 
        server->zonemgr = NULL;
4688
 
        server->interfacemgr = NULL;
4689
 
        ISC_LIST_INIT(server->viewlist);
4690
 
        server->in_roothints = NULL;
4691
 
        server->blackholeacl = NULL;
4692
 
 
4693
 
        CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
4694
 
                                     &server->in_roothints),
4695
 
                   "setting up root hints");
4696
 
 
4697
 
        CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
4698
 
                   "initializing reload event lock");
4699
 
        server->reload_event =
4700
 
                isc_event_allocate(ns_g_mctx, server,
4701
 
                                   NS_EVENT_RELOAD,
4702
 
                                   ns_server_reload,
4703
 
                                   server,
4704
 
                                   sizeof(isc_event_t));
4705
 
        CHECKFATAL(server->reload_event == NULL ?
4706
 
                   ISC_R_NOMEMORY : ISC_R_SUCCESS,
4707
 
                   "allocating reload event");
4708
 
 
4709
 
        CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy,
4710
 
                                 ns_g_engine, ISC_ENTROPY_GOODONLY),
4711
 
                   "initializing DST");
4712
 
 
4713
 
        server->tkeyctx = NULL;
4714
 
        CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
4715
 
                                      &server->tkeyctx),
4716
 
                   "creating TKEY context");
4717
 
 
4718
 
        /*
4719
 
         * Setup the server task, which is responsible for coordinating
4720
 
         * startup and shutdown of the server.
4721
 
         */
4722
 
        CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
4723
 
                   "creating server task");
4724
 
        isc_task_setname(server->task, "server", server);
4725
 
        CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
4726
 
                   "isc_task_onshutdown");
4727
 
        CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
4728
 
                   "isc_app_onrun");
4729
 
 
4730
 
        server->interface_timer = NULL;
4731
 
        server->heartbeat_timer = NULL;
4732
 
        server->pps_timer = NULL;
4733
 
 
4734
 
        server->interface_interval = 0;
4735
 
        server->heartbeat_interval = 0;
4736
 
 
4737
 
        CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
4738
 
                                      ns_g_socketmgr, &server->zonemgr),
4739
 
                   "dns_zonemgr_create");
4740
 
 
4741
 
        server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
4742
 
        CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
4743
 
                   "isc_mem_strdup");
4744
 
        server->nsstats = NULL;
4745
 
        server->rcvquerystats = NULL;
4746
 
        server->opcodestats = NULL;
4747
 
        server->zonestats = NULL;
4748
 
        server->resolverstats = NULL;
4749
 
        server->sockstats = NULL;
4750
 
        CHECKFATAL(isc_stats_create(server->mctx, &server->sockstats,
4751
 
                                    isc_sockstatscounter_max),
4752
 
                   "isc_stats_create");
4753
 
        isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats);
4754
 
 
4755
 
        server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys");
4756
 
        CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY :
4757
 
                                                  ISC_R_SUCCESS,
4758
 
                   "isc_mem_strdup");
4759
 
 
4760
 
        server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
4761
 
        CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
4762
 
                   "isc_mem_strdup");
4763
 
 
4764
 
        server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
4765
 
        CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
4766
 
                   "isc_mem_strdup");
4767
 
 
4768
 
        server->hostname_set = ISC_FALSE;
4769
 
        server->hostname = NULL;
4770
 
        server->version_set = ISC_FALSE;
4771
 
        server->version = NULL;
4772
 
        server->server_usehostname = ISC_FALSE;
4773
 
        server->server_id = NULL;
4774
 
 
4775
 
        CHECKFATAL(isc_stats_create(ns_g_mctx, &server->nsstats,
4776
 
                                    dns_nsstatscounter_max),
4777
 
                   "dns_stats_create (server)");
4778
 
 
4779
 
        CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,
4780
 
                                             &server->rcvquerystats),
4781
 
                   "dns_stats_create (rcvquery)");
4782
 
 
4783
 
        CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),
4784
 
                   "dns_stats_create (opcode)");
4785
 
 
4786
 
        CHECKFATAL(isc_stats_create(ns_g_mctx, &server->zonestats,
4787
 
                                    dns_zonestatscounter_max),
4788
 
                   "dns_stats_create (zone)");
4789
 
 
4790
 
        CHECKFATAL(isc_stats_create(ns_g_mctx, &server->resolverstats,
4791
 
                                    dns_resstatscounter_max),
4792
 
                   "dns_stats_create (resolver)");
4793
 
 
4794
 
        server->flushonshutdown = ISC_FALSE;
4795
 
        server->log_queries = ISC_FALSE;
4796
 
 
4797
 
        server->controls = NULL;
4798
 
        CHECKFATAL(ns_controls_create(server, &server->controls),
4799
 
                   "ns_controls_create");
4800
 
        server->dispatchgen = 0;
4801
 
        ISC_LIST_INIT(server->dispatches);
4802
 
 
4803
 
        ISC_LIST_INIT(server->statschannels);
4804
 
 
4805
 
        ISC_LIST_INIT(server->cachelist);
4806
 
 
4807
 
        server->sessionkey = NULL;
4808
 
        server->session_keyfile = NULL;
4809
 
        server->session_keyname = NULL;
4810
 
        server->session_keyalg = DST_ALG_UNKNOWN;
4811
 
        server->session_keybits = 0;
4812
 
 
4813
 
        server->magic = NS_SERVER_MAGIC;
4814
 
        *serverp = server;
4815
 
}
4816
 
 
4817
 
void
4818
 
ns_server_destroy(ns_server_t **serverp) {
4819
 
        ns_server_t *server = *serverp;
4820
 
        REQUIRE(NS_SERVER_VALID(server));
4821
 
 
4822
 
        ns_controls_destroy(&server->controls);
4823
 
 
4824
 
        isc_stats_detach(&server->nsstats);
4825
 
        dns_stats_detach(&server->rcvquerystats);
4826
 
        dns_stats_detach(&server->opcodestats);
4827
 
        isc_stats_detach(&server->zonestats);
4828
 
        isc_stats_detach(&server->resolverstats);
4829
 
        isc_stats_detach(&server->sockstats);
4830
 
 
4831
 
        isc_mem_free(server->mctx, server->statsfile);
4832
 
        isc_mem_free(server->mctx, server->bindkeysfile);
4833
 
        isc_mem_free(server->mctx, server->dumpfile);
4834
 
        isc_mem_free(server->mctx, server->recfile);
4835
 
 
4836
 
        if (server->version != NULL)
4837
 
                isc_mem_free(server->mctx, server->version);
4838
 
        if (server->hostname != NULL)
4839
 
                isc_mem_free(server->mctx, server->hostname);
4840
 
        if (server->server_id != NULL)
4841
 
                isc_mem_free(server->mctx, server->server_id);
4842
 
 
4843
 
        dns_zonemgr_detach(&server->zonemgr);
4844
 
 
4845
 
        if (server->tkeyctx != NULL)
4846
 
                dns_tkeyctx_destroy(&server->tkeyctx);
4847
 
 
4848
 
        dst_lib_destroy();
4849
 
 
4850
 
        isc_event_free(&server->reload_event);
4851
 
 
4852
 
        INSIST(ISC_LIST_EMPTY(server->viewlist));
4853
 
        INSIST(ISC_LIST_EMPTY(server->cachelist));
4854
 
 
4855
 
        dns_aclenv_destroy(&server->aclenv);
4856
 
 
4857
 
        isc_quota_destroy(&server->recursionquota);
4858
 
        isc_quota_destroy(&server->tcpquota);
4859
 
        isc_quota_destroy(&server->xfroutquota);
4860
 
 
4861
 
        server->magic = 0;
4862
 
        isc_mem_put(server->mctx, server, sizeof(*server));
4863
 
        *serverp = NULL;
4864
 
}
4865
 
 
4866
 
static void
4867
 
fatal(const char *msg, isc_result_t result) {
4868
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4869
 
                      ISC_LOG_CRITICAL, "%s: %s", msg,
4870
 
                      isc_result_totext(result));
4871
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
4872
 
                      ISC_LOG_CRITICAL, "exiting (due to fatal error)");
4873
 
        exit(1);
4874
 
}
4875
 
 
4876
 
static void
4877
 
start_reserved_dispatches(ns_server_t *server) {
4878
 
 
4879
 
        REQUIRE(NS_SERVER_VALID(server));
4880
 
 
4881
 
        server->dispatchgen++;
4882
 
}
4883
 
 
4884
 
static void
4885
 
end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
4886
 
        ns_dispatch_t *dispatch, *nextdispatch;
4887
 
 
4888
 
        REQUIRE(NS_SERVER_VALID(server));
4889
 
 
4890
 
        for (dispatch = ISC_LIST_HEAD(server->dispatches);
4891
 
             dispatch != NULL;
4892
 
             dispatch = nextdispatch) {
4893
 
                nextdispatch = ISC_LIST_NEXT(dispatch, link);
4894
 
                if (!all && server->dispatchgen == dispatch-> dispatchgen)
4895
 
                        continue;
4896
 
                ISC_LIST_UNLINK(server->dispatches, dispatch, link);
4897
 
                dns_dispatch_detach(&dispatch->dispatch);
4898
 
                isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
4899
 
        }
4900
 
}
4901
 
 
4902
 
void
4903
 
ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) {
4904
 
        ns_dispatch_t *dispatch;
4905
 
        in_port_t port;
4906
 
        char addrbuf[ISC_SOCKADDR_FORMATSIZE];
4907
 
        isc_result_t result;
4908
 
        unsigned int attrs, attrmask;
4909
 
 
4910
 
        REQUIRE(NS_SERVER_VALID(server));
4911
 
 
4912
 
        port = isc_sockaddr_getport(addr);
4913
 
        if (port == 0 || port >= 1024)
4914
 
                return;
4915
 
 
4916
 
        for (dispatch = ISC_LIST_HEAD(server->dispatches);
4917
 
             dispatch != NULL;
4918
 
             dispatch = ISC_LIST_NEXT(dispatch, link)) {
4919
 
                if (isc_sockaddr_equal(&dispatch->addr, addr))
4920
 
                        break;
4921
 
        }
4922
 
        if (dispatch != NULL) {
4923
 
                dispatch->dispatchgen = server->dispatchgen;
4924
 
                return;
4925
 
        }
4926
 
 
4927
 
        dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
4928
 
        if (dispatch == NULL) {
4929
 
                result = ISC_R_NOMEMORY;
4930
 
                goto cleanup;
4931
 
        }
4932
 
 
4933
 
        dispatch->addr = *addr;
4934
 
        dispatch->dispatchgen = server->dispatchgen;
4935
 
        dispatch->dispatch = NULL;
4936
 
 
4937
 
        attrs = 0;
4938
 
        attrs |= DNS_DISPATCHATTR_UDP;
4939
 
        switch (isc_sockaddr_pf(addr)) {
4940
 
        case AF_INET:
4941
 
                attrs |= DNS_DISPATCHATTR_IPV4;
4942
 
                break;
4943
 
        case AF_INET6:
4944
 
                attrs |= DNS_DISPATCHATTR_IPV6;
4945
 
                break;
4946
 
        default:
4947
 
                result = ISC_R_NOTIMPLEMENTED;
4948
 
                goto cleanup;
4949
 
        }
4950
 
        attrmask = 0;
4951
 
        attrmask |= DNS_DISPATCHATTR_UDP;
4952
 
        attrmask |= DNS_DISPATCHATTR_TCP;
4953
 
        attrmask |= DNS_DISPATCHATTR_IPV4;
4954
 
        attrmask |= DNS_DISPATCHATTR_IPV6;
4955
 
 
4956
 
        result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
4957
 
                                     ns_g_taskmgr, &dispatch->addr, 4096,
4958
 
                                     1000, 32768, 16411, 16433,
4959
 
                                     attrs, attrmask, &dispatch->dispatch);
4960
 
        if (result != ISC_R_SUCCESS)
4961
 
                goto cleanup;
4962
 
 
4963
 
        ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
4964
 
 
4965
 
        return;
4966
 
 
4967
 
 cleanup:
4968
 
        if (dispatch != NULL)
4969
 
                isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
4970
 
        isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
4971
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4972
 
                      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
4973
 
                      "unable to create dispatch for reserved port %s: %s",
4974
 
                      addrbuf, isc_result_totext(result));
4975
 
}
4976
 
 
4977
 
 
4978
 
static isc_result_t
4979
 
loadconfig(ns_server_t *server) {
4980
 
        isc_result_t result;
4981
 
        start_reserved_dispatches(server);
4982
 
        result = load_configuration(ns_g_lwresdonly ?
4983
 
                                    lwresd_g_conffile : ns_g_conffile,
4984
 
                                    server, ISC_FALSE);
4985
 
        if (result == ISC_R_SUCCESS) {
4986
 
                end_reserved_dispatches(server, ISC_FALSE);
4987
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4988
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
4989
 
                              "reloading configuration succeeded");
4990
 
        } else {
4991
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
4992
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
4993
 
                              "reloading configuration failed: %s",
4994
 
                              isc_result_totext(result));
4995
 
        }
4996
 
        return (result);
4997
 
}
4998
 
 
4999
 
static isc_result_t
5000
 
reload(ns_server_t *server) {
5001
 
        isc_result_t result;
5002
 
        CHECK(loadconfig(server));
5003
 
 
5004
 
        result = load_zones(server, ISC_FALSE);
5005
 
        if (result == ISC_R_SUCCESS)
5006
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5007
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5008
 
                              "reloading zones succeeded");
5009
 
        else
5010
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5011
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5012
 
                              "reloading zones failed: %s",
5013
 
                              isc_result_totext(result));
5014
 
 
5015
 
 cleanup:
5016
 
        return (result);
5017
 
}
5018
 
 
5019
 
static void
5020
 
reconfig(ns_server_t *server) {
5021
 
        isc_result_t result;
5022
 
        CHECK(loadconfig(server));
5023
 
 
5024
 
        result = load_new_zones(server, ISC_FALSE);
5025
 
        if (result == ISC_R_SUCCESS)
5026
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5027
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5028
 
                              "any newly configured zones are now loaded");
5029
 
        else
5030
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5031
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5032
 
                              "loading new zones failed: %s",
5033
 
                              isc_result_totext(result));
5034
 
 
5035
 
 cleanup: ;
5036
 
}
5037
 
 
5038
 
/*
5039
 
 * Handle a reload event (from SIGHUP).
5040
 
 */
5041
 
static void
5042
 
ns_server_reload(isc_task_t *task, isc_event_t *event) {
5043
 
        ns_server_t *server = (ns_server_t *)event->ev_arg;
5044
 
 
5045
 
        INSIST(task = server->task);
5046
 
        UNUSED(task);
5047
 
 
5048
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5049
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5050
 
                      "received SIGHUP signal to reload zones");
5051
 
        (void)reload(server);
5052
 
 
5053
 
        LOCK(&server->reload_event_lock);
5054
 
        INSIST(server->reload_event == NULL);
5055
 
        server->reload_event = event;
5056
 
        UNLOCK(&server->reload_event_lock);
5057
 
}
5058
 
 
5059
 
void
5060
 
ns_server_reloadwanted(ns_server_t *server) {
5061
 
        LOCK(&server->reload_event_lock);
5062
 
        if (server->reload_event != NULL)
5063
 
                isc_task_send(server->task, &server->reload_event);
5064
 
        UNLOCK(&server->reload_event_lock);
5065
 
}
5066
 
 
5067
 
static char *
5068
 
next_token(char **stringp, const char *delim) {
5069
 
        char *res;
5070
 
 
5071
 
        do {
5072
 
                res = strsep(stringp, delim);
5073
 
                if (res == NULL)
5074
 
                        break;
5075
 
        } while (*res == '\0');
5076
 
        return (res);
5077
 
}
5078
 
 
5079
 
/*
5080
 
 * Find the zone specified in the control channel command 'args',
5081
 
 * if any.  If a zone is specified, point '*zonep' at it, otherwise
5082
 
 * set '*zonep' to NULL.
5083
 
 */
5084
 
static isc_result_t
5085
 
zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
5086
 
        char *input, *ptr;
5087
 
        const char *zonetxt;
5088
 
        char *classtxt;
5089
 
        const char *viewtxt = NULL;
5090
 
        dns_fixedname_t name;
5091
 
        isc_result_t result;
5092
 
        isc_buffer_t buf;
5093
 
        dns_view_t *view = NULL;
5094
 
        dns_rdataclass_t rdclass;
5095
 
 
5096
 
        REQUIRE(zonep != NULL && *zonep == NULL);
5097
 
 
5098
 
        input = args;
5099
 
 
5100
 
        /* Skip the command name. */
5101
 
        ptr = next_token(&input, " \t");
5102
 
        if (ptr == NULL)
5103
 
                return (ISC_R_UNEXPECTEDEND);
5104
 
 
5105
 
        /* Look for the zone name. */
5106
 
        zonetxt = next_token(&input, " \t");
5107
 
        if (zonetxt == NULL)
5108
 
                return (ISC_R_SUCCESS);
5109
 
 
5110
 
        /* Look for the optional class name. */
5111
 
        classtxt = next_token(&input, " \t");
5112
 
        if (classtxt != NULL) {
5113
 
                /* Look for the optional view name. */
5114
 
                viewtxt = next_token(&input, " \t");
5115
 
        }
5116
 
 
5117
 
        isc_buffer_init(&buf, zonetxt, strlen(zonetxt));
5118
 
        isc_buffer_add(&buf, strlen(zonetxt));
5119
 
        dns_fixedname_init(&name);
5120
 
        result = dns_name_fromtext(dns_fixedname_name(&name),
5121
 
                                   &buf, dns_rootname, 0, NULL);
5122
 
        if (result != ISC_R_SUCCESS)
5123
 
                goto fail1;
5124
 
 
5125
 
        if (classtxt != NULL) {
5126
 
                isc_textregion_t r;
5127
 
                r.base = classtxt;
5128
 
                r.length = strlen(classtxt);
5129
 
                result = dns_rdataclass_fromtext(&rdclass, &r);
5130
 
                if (result != ISC_R_SUCCESS)
5131
 
                        goto fail1;
5132
 
        } else
5133
 
                rdclass = dns_rdataclass_in;
5134
 
 
5135
 
        if (viewtxt == NULL) {
5136
 
                result = dns_viewlist_findzone(&server->viewlist,
5137
 
                                               dns_fixedname_name(&name),
5138
 
                                               ISC_TF(classtxt == NULL),
5139
 
                                               rdclass, zonep);
5140
 
        } else {
5141
 
                result = dns_viewlist_find(&server->viewlist, viewtxt,
5142
 
                                           rdclass, &view);
5143
 
                if (result != ISC_R_SUCCESS)
5144
 
                        goto fail1;
5145
 
 
5146
 
                result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
5147
 
                                     0, NULL, zonep);
5148
 
                dns_view_detach(&view);
5149
 
        }
5150
 
 
5151
 
        /* Partial match? */
5152
 
        if (result != ISC_R_SUCCESS && *zonep != NULL)
5153
 
                dns_zone_detach(zonep);
5154
 
        if (result == DNS_R_PARTIALMATCH)
5155
 
                result = ISC_R_NOTFOUND;
5156
 
 fail1:
5157
 
        return (result);
5158
 
}
5159
 
 
5160
 
/*
5161
 
 * Act on a "retransfer" command from the command channel.
5162
 
 */
5163
 
isc_result_t
5164
 
ns_server_retransfercommand(ns_server_t *server, char *args) {
5165
 
        isc_result_t result;
5166
 
        dns_zone_t *zone = NULL;
5167
 
        dns_zonetype_t type;
5168
 
 
5169
 
        result = zone_from_args(server, args, &zone);
5170
 
        if (result != ISC_R_SUCCESS)
5171
 
                return (result);
5172
 
        if (zone == NULL)
5173
 
                return (ISC_R_UNEXPECTEDEND);
5174
 
        type = dns_zone_gettype(zone);
5175
 
        if (type == dns_zone_slave || type == dns_zone_stub)
5176
 
                dns_zone_forcereload(zone);
5177
 
        else
5178
 
                result = ISC_R_NOTFOUND;
5179
 
        dns_zone_detach(&zone);
5180
 
        return (result);
5181
 
}
5182
 
 
5183
 
/*
5184
 
 * Act on a "reload" command from the command channel.
5185
 
 */
5186
 
isc_result_t
5187
 
ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
5188
 
        isc_result_t result;
5189
 
        dns_zone_t *zone = NULL;
5190
 
        dns_zonetype_t type;
5191
 
        const char *msg = NULL;
5192
 
 
5193
 
        result = zone_from_args(server, args, &zone);
5194
 
        if (result != ISC_R_SUCCESS)
5195
 
                return (result);
5196
 
        if (zone == NULL) {
5197
 
                result = reload(server);
5198
 
                if (result == ISC_R_SUCCESS)
5199
 
                        msg = "server reload successful";
5200
 
        } else {
5201
 
                type = dns_zone_gettype(zone);
5202
 
                if (type == dns_zone_slave || type == dns_zone_stub) {
5203
 
                        dns_zone_refresh(zone);
5204
 
                        dns_zone_detach(&zone);
5205
 
                        msg = "zone refresh queued";
5206
 
                } else {
5207
 
                        result = dns_zone_load(zone);
5208
 
                        dns_zone_detach(&zone);
5209
 
                        switch (result) {
5210
 
                        case ISC_R_SUCCESS:
5211
 
                                 msg = "zone reload successful";
5212
 
                                 break;
5213
 
                        case DNS_R_CONTINUE:
5214
 
                                msg = "zone reload queued";
5215
 
                                result = ISC_R_SUCCESS;
5216
 
                                break;
5217
 
                        case DNS_R_UPTODATE:
5218
 
                                msg = "zone reload up-to-date";
5219
 
                                result = ISC_R_SUCCESS;
5220
 
                                break;
5221
 
                        default:
5222
 
                                /* failure message will be generated by rndc */
5223
 
                                break;
5224
 
                        }
5225
 
                }
5226
 
        }
5227
 
        if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
5228
 
                isc_buffer_putmem(text, (const unsigned char *)msg,
5229
 
                                  strlen(msg) + 1);
5230
 
        return (result);
5231
 
}
5232
 
 
5233
 
/*
5234
 
 * Act on a "reconfig" command from the command channel.
5235
 
 */
5236
 
isc_result_t
5237
 
ns_server_reconfigcommand(ns_server_t *server, char *args) {
5238
 
        UNUSED(args);
5239
 
 
5240
 
        reconfig(server);
5241
 
        return (ISC_R_SUCCESS);
5242
 
}
5243
 
 
5244
 
/*
5245
 
 * Act on a "notify" command from the command channel.
5246
 
 */
5247
 
isc_result_t
5248
 
ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
5249
 
        isc_result_t result;
5250
 
        dns_zone_t *zone = NULL;
5251
 
        const unsigned char msg[] = "zone notify queued";
5252
 
 
5253
 
        result = zone_from_args(server, args, &zone);
5254
 
        if (result != ISC_R_SUCCESS)
5255
 
                return (result);
5256
 
        if (zone == NULL)
5257
 
                return (ISC_R_UNEXPECTEDEND);
5258
 
 
5259
 
        dns_zone_notify(zone);
5260
 
        dns_zone_detach(&zone);
5261
 
        if (sizeof(msg) <= isc_buffer_availablelength(text))
5262
 
                isc_buffer_putmem(text, msg, sizeof(msg));
5263
 
 
5264
 
        return (ISC_R_SUCCESS);
5265
 
}
5266
 
 
5267
 
/*
5268
 
 * Act on a "refresh" command from the command channel.
5269
 
 */
5270
 
isc_result_t
5271
 
ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
5272
 
        isc_result_t result;
5273
 
        dns_zone_t *zone = NULL;
5274
 
        const unsigned char msg1[] = "zone refresh queued";
5275
 
        const unsigned char msg2[] = "not a slave or stub zone";
5276
 
        dns_zonetype_t type;
5277
 
 
5278
 
        result = zone_from_args(server, args, &zone);
5279
 
        if (result != ISC_R_SUCCESS)
5280
 
                return (result);
5281
 
        if (zone == NULL)
5282
 
                return (ISC_R_UNEXPECTEDEND);
5283
 
 
5284
 
        type = dns_zone_gettype(zone);
5285
 
        if (type == dns_zone_slave || type == dns_zone_stub) {
5286
 
                dns_zone_refresh(zone);
5287
 
                dns_zone_detach(&zone);
5288
 
                if (sizeof(msg1) <= isc_buffer_availablelength(text))
5289
 
                        isc_buffer_putmem(text, msg1, sizeof(msg1));
5290
 
                return (ISC_R_SUCCESS);
5291
 
        }
5292
 
 
5293
 
        dns_zone_detach(&zone);
5294
 
        if (sizeof(msg2) <= isc_buffer_availablelength(text))
5295
 
                isc_buffer_putmem(text, msg2, sizeof(msg2));
5296
 
        return (ISC_R_FAILURE);
5297
 
}
5298
 
 
5299
 
isc_result_t
5300
 
ns_server_togglequerylog(ns_server_t *server) {
5301
 
        server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
5302
 
 
5303
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5304
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5305
 
                      "query logging is now %s",
5306
 
                      server->log_queries ? "on" : "off");
5307
 
        return (ISC_R_SUCCESS);
5308
 
}
5309
 
 
5310
 
static isc_result_t
5311
 
ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
5312
 
                         cfg_aclconfctx_t *actx,
5313
 
                         isc_mem_t *mctx, ns_listenlist_t **target)
5314
 
{
5315
 
        isc_result_t result;
5316
 
        const cfg_listelt_t *element;
5317
 
        ns_listenlist_t *dlist = NULL;
5318
 
 
5319
 
        REQUIRE(target != NULL && *target == NULL);
5320
 
 
5321
 
        result = ns_listenlist_create(mctx, &dlist);
5322
 
        if (result != ISC_R_SUCCESS)
5323
 
                return (result);
5324
 
 
5325
 
        for (element = cfg_list_first(listenlist);
5326
 
             element != NULL;
5327
 
             element = cfg_list_next(element))
5328
 
        {
5329
 
                ns_listenelt_t *delt = NULL;
5330
 
                const cfg_obj_t *listener = cfg_listelt_value(element);
5331
 
                result = ns_listenelt_fromconfig(listener, config, actx,
5332
 
                                                 mctx, &delt);
5333
 
                if (result != ISC_R_SUCCESS)
5334
 
                        goto cleanup;
5335
 
                ISC_LIST_APPEND(dlist->elts, delt, link);
5336
 
        }
5337
 
        *target = dlist;
5338
 
        return (ISC_R_SUCCESS);
5339
 
 
5340
 
 cleanup:
5341
 
        ns_listenlist_detach(&dlist);
5342
 
        return (result);
5343
 
}
5344
 
 
5345
 
/*
5346
 
 * Create a listen list from the corresponding configuration
5347
 
 * data structure.
5348
 
 */
5349
 
static isc_result_t
5350
 
ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
5351
 
                        cfg_aclconfctx_t *actx,
5352
 
                        isc_mem_t *mctx, ns_listenelt_t **target)
5353
 
{
5354
 
        isc_result_t result;
5355
 
        const cfg_obj_t *portobj;
5356
 
        in_port_t port;
5357
 
        ns_listenelt_t *delt = NULL;
5358
 
        REQUIRE(target != NULL && *target == NULL);
5359
 
 
5360
 
        portobj = cfg_tuple_get(listener, "port");
5361
 
        if (!cfg_obj_isuint32(portobj)) {
5362
 
                if (ns_g_port != 0) {
5363
 
                        port = ns_g_port;
5364
 
                } else {
5365
 
                        result = ns_config_getport(config, &port);
5366
 
                        if (result != ISC_R_SUCCESS)
5367
 
                                return (result);
5368
 
                }
5369
 
        } else {
5370
 
                if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
5371
 
                        cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
5372
 
                                    "port value '%u' is out of range",
5373
 
                                    cfg_obj_asuint32(portobj));
5374
 
                        return (ISC_R_RANGE);
5375
 
                }
5376
 
                port = (in_port_t)cfg_obj_asuint32(portobj);
5377
 
        }
5378
 
 
5379
 
        result = ns_listenelt_create(mctx, port, NULL, &delt);
5380
 
        if (result != ISC_R_SUCCESS)
5381
 
                return (result);
5382
 
 
5383
 
        result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
5384
 
                                   config, ns_g_lctx, actx, mctx, 0,
5385
 
                                   &delt->acl);
5386
 
        if (result != ISC_R_SUCCESS) {
5387
 
                ns_listenelt_destroy(delt);
5388
 
                return (result);
5389
 
        }
5390
 
        *target = delt;
5391
 
        return (ISC_R_SUCCESS);
5392
 
}
5393
 
 
5394
 
isc_result_t
5395
 
ns_server_dumpstats(ns_server_t *server) {
5396
 
        isc_result_t result;
5397
 
        FILE *fp = NULL;
5398
 
 
5399
 
        CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
5400
 
                "could not open statistics dump file", server->statsfile);
5401
 
 
5402
 
        result = ns_stats_dump(server, fp);
5403
 
        CHECK(result);
5404
 
 
5405
 
 cleanup:
5406
 
        if (fp != NULL)
5407
 
                (void)isc_stdio_close(fp);
5408
 
        if (result == ISC_R_SUCCESS)
5409
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5410
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5411
 
                              "dumpstats complete");
5412
 
        else
5413
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5414
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5415
 
                              "dumpstats failed: %s",
5416
 
                              dns_result_totext(result));
5417
 
        return (result);
5418
 
}
5419
 
 
5420
 
static isc_result_t
5421
 
add_zone_tolist(dns_zone_t *zone, void *uap) {
5422
 
        struct dumpcontext *dctx = uap;
5423
 
        struct zonelistentry *zle;
5424
 
 
5425
 
        zle = isc_mem_get(dctx->mctx, sizeof *zle);
5426
 
        if (zle ==  NULL)
5427
 
                return (ISC_R_NOMEMORY);
5428
 
        zle->zone = NULL;
5429
 
        dns_zone_attach(zone, &zle->zone);
5430
 
        ISC_LINK_INIT(zle, link);
5431
 
        ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
5432
 
        return (ISC_R_SUCCESS);
5433
 
}
5434
 
 
5435
 
static isc_result_t
5436
 
add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
5437
 
        struct viewlistentry *vle;
5438
 
        isc_result_t result = ISC_R_SUCCESS;
5439
 
 
5440
 
        /*
5441
 
         * Prevent duplicate views.
5442
 
         */
5443
 
        for (vle = ISC_LIST_HEAD(dctx->viewlist);
5444
 
             vle != NULL;
5445
 
             vle = ISC_LIST_NEXT(vle, link))
5446
 
                if (vle->view == view)
5447
 
                        return (ISC_R_SUCCESS);
5448
 
 
5449
 
        vle = isc_mem_get(dctx->mctx, sizeof *vle);
5450
 
        if (vle == NULL)
5451
 
                return (ISC_R_NOMEMORY);
5452
 
        vle->view = NULL;
5453
 
        dns_view_attach(view, &vle->view);
5454
 
        ISC_LINK_INIT(vle, link);
5455
 
        ISC_LIST_INIT(vle->zonelist);
5456
 
        ISC_LIST_APPEND(dctx->viewlist, vle, link);
5457
 
        if (dctx->dumpzones)
5458
 
                result = dns_zt_apply(view->zonetable, ISC_TRUE,
5459
 
                                      add_zone_tolist, dctx);
5460
 
        return (result);
5461
 
}
5462
 
 
5463
 
static void
5464
 
dumpcontext_destroy(struct dumpcontext *dctx) {
5465
 
        struct viewlistentry *vle;
5466
 
        struct zonelistentry *zle;
5467
 
 
5468
 
        vle = ISC_LIST_HEAD(dctx->viewlist);
5469
 
        while (vle != NULL) {
5470
 
                ISC_LIST_UNLINK(dctx->viewlist, vle, link);
5471
 
                zle = ISC_LIST_HEAD(vle->zonelist);
5472
 
                while (zle != NULL) {
5473
 
                        ISC_LIST_UNLINK(vle->zonelist, zle, link);
5474
 
                        dns_zone_detach(&zle->zone);
5475
 
                        isc_mem_put(dctx->mctx, zle, sizeof *zle);
5476
 
                        zle = ISC_LIST_HEAD(vle->zonelist);
5477
 
                }
5478
 
                dns_view_detach(&vle->view);
5479
 
                isc_mem_put(dctx->mctx, vle, sizeof *vle);
5480
 
                vle = ISC_LIST_HEAD(dctx->viewlist);
5481
 
        }
5482
 
        if (dctx->version != NULL)
5483
 
                dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
5484
 
        if (dctx->db != NULL)
5485
 
                dns_db_detach(&dctx->db);
5486
 
        if (dctx->cache != NULL)
5487
 
                dns_db_detach(&dctx->cache);
5488
 
        if (dctx->task != NULL)
5489
 
                isc_task_detach(&dctx->task);
5490
 
        if (dctx->fp != NULL)
5491
 
                (void)isc_stdio_close(dctx->fp);
5492
 
        if (dctx->mdctx != NULL)
5493
 
                dns_dumpctx_detach(&dctx->mdctx);
5494
 
        isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
5495
 
}
5496
 
 
5497
 
static void
5498
 
dumpdone(void *arg, isc_result_t result) {
5499
 
        struct dumpcontext *dctx = arg;
5500
 
        char buf[1024+32];
5501
 
        const dns_master_style_t *style;
5502
 
 
5503
 
        if (result != ISC_R_SUCCESS)
5504
 
                goto cleanup;
5505
 
        if (dctx->mdctx != NULL)
5506
 
                dns_dumpctx_detach(&dctx->mdctx);
5507
 
        if (dctx->view == NULL) {
5508
 
                dctx->view = ISC_LIST_HEAD(dctx->viewlist);
5509
 
                if (dctx->view == NULL)
5510
 
                        goto done;
5511
 
                INSIST(dctx->zone == NULL);
5512
 
        } else
5513
 
                goto resume;
5514
 
 nextview:
5515
 
        fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
5516
 
 resume:
5517
 
        if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) {
5518
 
                fprintf(dctx->fp,
5519
 
                        ";\n; Cache of view '%s' is shared as '%s'\n",
5520
 
                        dctx->view->view->name,
5521
 
                        dns_cache_getname(dctx->view->view->cache));
5522
 
        } else if (dctx->zone == NULL && dctx->cache == NULL &&
5523
 
                   dctx->dumpcache)
5524
 
        {
5525
 
                style = &dns_master_style_cache;
5526
 
                /* start cache dump */
5527
 
                if (dctx->view->view->cachedb != NULL)
5528
 
                        dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
5529
 
                if (dctx->cache != NULL) {
5530
 
                        fprintf(dctx->fp,
5531
 
                                ";\n; Cache dump of view '%s' (cache %s)\n;\n",
5532
 
                                dctx->view->view->name,
5533
 
                                dns_cache_getname(dctx->view->view->cache));
5534
 
                        result = dns_master_dumptostreaminc(dctx->mctx,
5535
 
                                                            dctx->cache, NULL,
5536
 
                                                            style, dctx->fp,
5537
 
                                                            dctx->task,
5538
 
                                                            dumpdone, dctx,
5539
 
                                                            &dctx->mdctx);
5540
 
                        if (result == DNS_R_CONTINUE)
5541
 
                                return;
5542
 
                        if (result == ISC_R_NOTIMPLEMENTED)
5543
 
                                fprintf(dctx->fp, "; %s\n",
5544
 
                                        dns_result_totext(result));
5545
 
                        else if (result != ISC_R_SUCCESS)
5546
 
                                goto cleanup;
5547
 
                }
5548
 
        }
5549
 
        if (dctx->cache != NULL) {
5550
 
                dns_adb_dump(dctx->view->view->adb, dctx->fp);
5551
 
                dns_resolver_printbadcache(dctx->view->view->resolver,
5552
 
                                           dctx->fp);
5553
 
                dns_db_detach(&dctx->cache);
5554
 
        }
5555
 
        if (dctx->dumpzones) {
5556
 
                style = &dns_master_style_full;
5557
 
 nextzone:
5558
 
                if (dctx->version != NULL)
5559
 
                        dns_db_closeversion(dctx->db, &dctx->version,
5560
 
                                            ISC_FALSE);
5561
 
                if (dctx->db != NULL)
5562
 
                        dns_db_detach(&dctx->db);
5563
 
                if (dctx->zone == NULL)
5564
 
                        dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
5565
 
                else
5566
 
                        dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
5567
 
                if (dctx->zone != NULL) {
5568
 
                        /* start zone dump */
5569
 
                        dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
5570
 
                        fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
5571
 
                        result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
5572
 
                        if (result != ISC_R_SUCCESS) {
5573
 
                                fprintf(dctx->fp, "; %s\n",
5574
 
                                        dns_result_totext(result));
5575
 
                                goto nextzone;
5576
 
                        }
5577
 
                        dns_db_currentversion(dctx->db, &dctx->version);
5578
 
                        result = dns_master_dumptostreaminc(dctx->mctx,
5579
 
                                                            dctx->db,
5580
 
                                                            dctx->version,
5581
 
                                                            style, dctx->fp,
5582
 
                                                            dctx->task,
5583
 
                                                            dumpdone, dctx,
5584
 
                                                            &dctx->mdctx);
5585
 
                        if (result == DNS_R_CONTINUE)
5586
 
                                return;
5587
 
                        if (result == ISC_R_NOTIMPLEMENTED) {
5588
 
                                fprintf(dctx->fp, "; %s\n",
5589
 
                                        dns_result_totext(result));
5590
 
                                result = ISC_R_SUCCESS;
5591
 
                                goto nextzone;
5592
 
                        }
5593
 
                        if (result != ISC_R_SUCCESS)
5594
 
                                goto cleanup;
5595
 
                }
5596
 
        }
5597
 
        if (dctx->view != NULL)
5598
 
                dctx->view = ISC_LIST_NEXT(dctx->view, link);
5599
 
        if (dctx->view != NULL)
5600
 
                goto nextview;
5601
 
 done:
5602
 
        fprintf(dctx->fp, "; Dump complete\n");
5603
 
        result = isc_stdio_flush(dctx->fp);
5604
 
        if (result == ISC_R_SUCCESS)
5605
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5606
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5607
 
                              "dumpdb complete");
5608
 
 cleanup:
5609
 
        if (result != ISC_R_SUCCESS)
5610
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5611
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5612
 
                              "dumpdb failed: %s", dns_result_totext(result));
5613
 
        dumpcontext_destroy(dctx);
5614
 
}
5615
 
 
5616
 
isc_result_t
5617
 
ns_server_dumpdb(ns_server_t *server, char *args) {
5618
 
        struct dumpcontext *dctx = NULL;
5619
 
        dns_view_t *view;
5620
 
        isc_result_t result;
5621
 
        char *ptr;
5622
 
        const char *sep;
5623
 
 
5624
 
        /* Skip the command name. */
5625
 
        ptr = next_token(&args, " \t");
5626
 
        if (ptr == NULL)
5627
 
                return (ISC_R_UNEXPECTEDEND);
5628
 
 
5629
 
        dctx = isc_mem_get(server->mctx, sizeof(*dctx));
5630
 
        if (dctx == NULL)
5631
 
                return (ISC_R_NOMEMORY);
5632
 
 
5633
 
        dctx->mctx = server->mctx;
5634
 
        dctx->dumpcache = ISC_TRUE;
5635
 
        dctx->dumpzones = ISC_FALSE;
5636
 
        dctx->fp = NULL;
5637
 
        ISC_LIST_INIT(dctx->viewlist);
5638
 
        dctx->view = NULL;
5639
 
        dctx->zone = NULL;
5640
 
        dctx->cache = NULL;
5641
 
        dctx->mdctx = NULL;
5642
 
        dctx->db = NULL;
5643
 
        dctx->cache = NULL;
5644
 
        dctx->task = NULL;
5645
 
        dctx->version = NULL;
5646
 
        isc_task_attach(server->task, &dctx->task);
5647
 
 
5648
 
        CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
5649
 
                "could not open dump file", server->dumpfile);
5650
 
 
5651
 
        sep = (args == NULL) ? "" : ": ";
5652
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5653
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5654
 
                      "dumpdb started%s%s", sep, (args != NULL) ? args : "");
5655
 
 
5656
 
        ptr = next_token(&args, " \t");
5657
 
        if (ptr != NULL && strcmp(ptr, "-all") == 0) {
5658
 
                dctx->dumpzones = ISC_TRUE;
5659
 
                dctx->dumpcache = ISC_TRUE;
5660
 
                ptr = next_token(&args, " \t");
5661
 
        } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
5662
 
                dctx->dumpzones = ISC_FALSE;
5663
 
                dctx->dumpcache = ISC_TRUE;
5664
 
                ptr = next_token(&args, " \t");
5665
 
        } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
5666
 
                dctx->dumpzones = ISC_TRUE;
5667
 
                dctx->dumpcache = ISC_FALSE;
5668
 
                ptr = next_token(&args, " \t");
5669
 
        }
5670
 
 
5671
 
 nextview:
5672
 
        for (view = ISC_LIST_HEAD(server->viewlist);
5673
 
             view != NULL;
5674
 
             view = ISC_LIST_NEXT(view, link))
5675
 
        {
5676
 
                if (ptr != NULL && strcmp(view->name, ptr) != 0)
5677
 
                        continue;
5678
 
                CHECK(add_view_tolist(dctx, view));
5679
 
        }
5680
 
        if (ptr != NULL) {
5681
 
                ptr = next_token(&args, " \t");
5682
 
                if (ptr != NULL)
5683
 
                        goto nextview;
5684
 
        }
5685
 
        dumpdone(dctx, ISC_R_SUCCESS);
5686
 
        return (ISC_R_SUCCESS);
5687
 
 
5688
 
 cleanup:
5689
 
        if (dctx != NULL)
5690
 
                dumpcontext_destroy(dctx);
5691
 
        return (result);
5692
 
}
5693
 
 
5694
 
isc_result_t
5695
 
ns_server_dumprecursing(ns_server_t *server) {
5696
 
        FILE *fp = NULL;
5697
 
        isc_result_t result;
5698
 
 
5699
 
        CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
5700
 
                "could not open dump file", server->recfile);
5701
 
        fprintf(fp,";\n; Recursing Queries\n;\n");
5702
 
        ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
5703
 
        fprintf(fp, "; Dump complete\n");
5704
 
 
5705
 
 cleanup:
5706
 
        if (fp != NULL)
5707
 
                result = isc_stdio_close(fp);
5708
 
        if (result == ISC_R_SUCCESS)
5709
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5710
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5711
 
                              "dumprecursing complete");
5712
 
        else
5713
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5714
 
                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5715
 
                              "dumprecursing failed: %s",
5716
 
                              dns_result_totext(result));
5717
 
        return (result);
5718
 
}
5719
 
 
5720
 
isc_result_t
5721
 
ns_server_setdebuglevel(ns_server_t *server, char *args) {
5722
 
        char *ptr;
5723
 
        char *levelstr;
5724
 
        char *endp;
5725
 
        long newlevel;
5726
 
 
5727
 
        UNUSED(server);
5728
 
 
5729
 
        /* Skip the command name. */
5730
 
        ptr = next_token(&args, " \t");
5731
 
        if (ptr == NULL)
5732
 
                return (ISC_R_UNEXPECTEDEND);
5733
 
 
5734
 
        /* Look for the new level name. */
5735
 
        levelstr = next_token(&args, " \t");
5736
 
        if (levelstr == NULL) {
5737
 
                if (ns_g_debuglevel < 99)
5738
 
                        ns_g_debuglevel++;
5739
 
        } else {
5740
 
                newlevel = strtol(levelstr, &endp, 10);
5741
 
                if (*endp != '\0' || newlevel < 0 || newlevel > 99)
5742
 
                        return (ISC_R_RANGE);
5743
 
                ns_g_debuglevel = (unsigned int)newlevel;
5744
 
        }
5745
 
        isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
5746
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5747
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5748
 
                      "debug level is now %d", ns_g_debuglevel);
5749
 
        return (ISC_R_SUCCESS);
5750
 
}
5751
 
 
5752
 
isc_result_t
5753
 
ns_server_validation(ns_server_t *server, char *args) {
5754
 
        char *ptr, *viewname;
5755
 
        dns_view_t *view;
5756
 
        isc_boolean_t changed = ISC_FALSE;
5757
 
        isc_result_t result;
5758
 
        isc_boolean_t enable;
5759
 
 
5760
 
        /* Skip the command name. */
5761
 
        ptr = next_token(&args, " \t");
5762
 
        if (ptr == NULL)
5763
 
                return (ISC_R_UNEXPECTEDEND);
5764
 
 
5765
 
        /* Find out what we are to do. */
5766
 
        ptr = next_token(&args, " \t");
5767
 
        if (ptr == NULL)
5768
 
                return (ISC_R_UNEXPECTEDEND);
5769
 
 
5770
 
        if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
5771
 
            !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
5772
 
                enable = ISC_TRUE;
5773
 
        else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
5774
 
                 !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
5775
 
                enable = ISC_FALSE;
5776
 
        else
5777
 
                return (DNS_R_SYNTAX);
5778
 
 
5779
 
        /* Look for the view name. */
5780
 
        viewname = next_token(&args, " \t");
5781
 
 
5782
 
        result = isc_task_beginexclusive(server->task);
5783
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
5784
 
        for (view = ISC_LIST_HEAD(server->viewlist);
5785
 
             view != NULL;
5786
 
             view = ISC_LIST_NEXT(view, link))
5787
 
        {
5788
 
                if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
5789
 
                        continue;
5790
 
                result = dns_view_flushcache(view);
5791
 
                if (result != ISC_R_SUCCESS)
5792
 
                        goto out;
5793
 
                view->enablevalidation = enable;
5794
 
                changed = ISC_TRUE;
5795
 
        }
5796
 
        if (changed)
5797
 
                result = ISC_R_SUCCESS;
5798
 
        else
5799
 
                result = ISC_R_FAILURE;
5800
 
 out:
5801
 
        isc_task_endexclusive(server->task);
5802
 
        return (result);
5803
 
}
5804
 
 
5805
 
isc_result_t
5806
 
ns_server_flushcache(ns_server_t *server, char *args) {
5807
 
        char *ptr, *viewname;
5808
 
        dns_view_t *view;
5809
 
        isc_boolean_t flushed;
5810
 
        isc_boolean_t found;
5811
 
        isc_result_t result;
5812
 
        ns_cache_t *nsc;
5813
 
 
5814
 
        /* Skip the command name. */
5815
 
        ptr = next_token(&args, " \t");
5816
 
        if (ptr == NULL)
5817
 
                return (ISC_R_UNEXPECTEDEND);
5818
 
 
5819
 
        /* Look for the view name. */
5820
 
        viewname = next_token(&args, " \t");
5821
 
 
5822
 
        result = isc_task_beginexclusive(server->task);
5823
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
5824
 
        flushed = ISC_TRUE;
5825
 
        found = ISC_FALSE;
5826
 
 
5827
 
        /*
5828
 
         * Flushing a cache is tricky when caches are shared by multiple views.
5829
 
         * We first identify which caches should be flushed in the local cache
5830
 
         * list, flush these caches, and then update other views that refer to
5831
 
         * the flushed cache DB.
5832
 
         */
5833
 
        if (viewname != NULL) {
5834
 
                /*
5835
 
                 * Mark caches that need to be flushed.  This is an O(#view^2)
5836
 
                 * operation in the very worst case, but should be normally
5837
 
                 * much more lightweight because only a few (most typically just
5838
 
                 * one) views will match.
5839
 
                 */
5840
 
                for (view = ISC_LIST_HEAD(server->viewlist);
5841
 
                     view != NULL;
5842
 
                     view = ISC_LIST_NEXT(view, link))
5843
 
                {
5844
 
                        if (strcasecmp(viewname, view->name) != 0)
5845
 
                                continue;
5846
 
                        found = ISC_TRUE;
5847
 
                        for (nsc = ISC_LIST_HEAD(server->cachelist);
5848
 
                             nsc != NULL;
5849
 
                             nsc = ISC_LIST_NEXT(nsc, link)) {
5850
 
                                if (nsc->cache == view->cache)
5851
 
                                        break;
5852
 
                        }
5853
 
                        INSIST(nsc != NULL);
5854
 
                        nsc->needflush = ISC_TRUE;
5855
 
                }
5856
 
        } else
5857
 
                found = ISC_TRUE;
5858
 
 
5859
 
        /* Perform flush */
5860
 
        for (nsc = ISC_LIST_HEAD(server->cachelist);
5861
 
             nsc != NULL;
5862
 
             nsc = ISC_LIST_NEXT(nsc, link)) {
5863
 
                if (viewname != NULL && !nsc->needflush)
5864
 
                        continue;
5865
 
                nsc->needflush = ISC_TRUE;
5866
 
                result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE);
5867
 
                if (result != ISC_R_SUCCESS) {
5868
 
                        flushed = ISC_FALSE;
5869
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5870
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5871
 
                                      "flushing cache in view '%s' failed: %s",
5872
 
                                      nsc->primaryview->name,
5873
 
                                      isc_result_totext(result));
5874
 
                }
5875
 
        }
5876
 
 
5877
 
        /*
5878
 
         * Fix up views that share a flushed cache: let the views update the
5879
 
         * cache DB they're referring to.  This could also be an expensive
5880
 
         * operation, but should typically be marginal: the inner loop is only
5881
 
         * necessary for views that share a cache, and if there are many such
5882
 
         * views the number of shared cache should normally be small.
5883
 
         * A worst case is that we have n views and n/2 caches, each shared by
5884
 
         * two views.  Then this will be a O(n^2/4) operation.
5885
 
         */
5886
 
        for (view = ISC_LIST_HEAD(server->viewlist);
5887
 
             view != NULL;
5888
 
             view = ISC_LIST_NEXT(view, link))
5889
 
        {
5890
 
                if (!dns_view_iscacheshared(view))
5891
 
                        continue;
5892
 
                for (nsc = ISC_LIST_HEAD(server->cachelist);
5893
 
                     nsc != NULL;
5894
 
                     nsc = ISC_LIST_NEXT(nsc, link)) {
5895
 
                        if (!nsc->needflush || nsc->cache != view->cache)
5896
 
                                continue;
5897
 
                        result = dns_view_flushcache2(view, ISC_TRUE);
5898
 
                        if (result != ISC_R_SUCCESS) {
5899
 
                                flushed = ISC_FALSE;
5900
 
                                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5901
 
                                              NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5902
 
                                              "fixing cache in view '%s' "
5903
 
                                              "failed: %s", view->name,
5904
 
                                              isc_result_totext(result));
5905
 
                        }
5906
 
                }
5907
 
        }
5908
 
 
5909
 
        /* Cleanup the cache list. */
5910
 
        for (nsc = ISC_LIST_HEAD(server->cachelist);
5911
 
             nsc != NULL;
5912
 
             nsc = ISC_LIST_NEXT(nsc, link)) {
5913
 
                nsc->needflush = ISC_FALSE;
5914
 
        }
5915
 
 
5916
 
        if (flushed && found) {
5917
 
                if (viewname != NULL)
5918
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5919
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5920
 
                                      "flushing cache in view '%s' succeeded",
5921
 
                                      viewname);
5922
 
                else
5923
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5924
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
5925
 
                                      "flushing caches in all views succeeded");
5926
 
                result = ISC_R_SUCCESS;
5927
 
        } else {
5928
 
                if (!found) {
5929
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5930
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5931
 
                                      "flushing cache in view '%s' failed: "
5932
 
                                      "view not found", viewname);
5933
 
                        result = ISC_R_NOTFOUND;
5934
 
                } else
5935
 
                        result = ISC_R_FAILURE;
5936
 
        }
5937
 
        isc_task_endexclusive(server->task);
5938
 
        return (result);
5939
 
}
5940
 
 
5941
 
isc_result_t
5942
 
ns_server_flushname(ns_server_t *server, char *args) {
5943
 
        char *ptr, *target, *viewname;
5944
 
        dns_view_t *view;
5945
 
        isc_boolean_t flushed;
5946
 
        isc_boolean_t found;
5947
 
        isc_result_t result;
5948
 
        isc_buffer_t b;
5949
 
        dns_fixedname_t fixed;
5950
 
        dns_name_t *name;
5951
 
 
5952
 
        /* Skip the command name. */
5953
 
        ptr = next_token(&args, " \t");
5954
 
        if (ptr == NULL)
5955
 
                return (ISC_R_UNEXPECTEDEND);
5956
 
 
5957
 
        /* Find the domain name to flush. */
5958
 
        target = next_token(&args, " \t");
5959
 
        if (target == NULL)
5960
 
                return (ISC_R_UNEXPECTEDEND);
5961
 
 
5962
 
        isc_buffer_init(&b, target, strlen(target));
5963
 
        isc_buffer_add(&b, strlen(target));
5964
 
        dns_fixedname_init(&fixed);
5965
 
        name = dns_fixedname_name(&fixed);
5966
 
        result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
5967
 
        if (result != ISC_R_SUCCESS)
5968
 
                return (result);
5969
 
 
5970
 
        /* Look for the view name. */
5971
 
        viewname = next_token(&args, " \t");
5972
 
 
5973
 
        result = isc_task_beginexclusive(server->task);
5974
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
5975
 
        flushed = ISC_TRUE;
5976
 
        found = ISC_FALSE;
5977
 
        for (view = ISC_LIST_HEAD(server->viewlist);
5978
 
             view != NULL;
5979
 
             view = ISC_LIST_NEXT(view, link))
5980
 
        {
5981
 
                if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
5982
 
                        continue;
5983
 
                found = ISC_TRUE;
5984
 
                /*
5985
 
                 * It's a little inefficient to try flushing name for all views
5986
 
                 * if some of the views share a single cache.  But since the
5987
 
                 * operation is lightweight we prefer simplicity here.
5988
 
                 */
5989
 
                result = dns_view_flushname(view, name);
5990
 
                if (result != ISC_R_SUCCESS) {
5991
 
                        flushed = ISC_FALSE;
5992
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
5993
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
5994
 
                                      "flushing name '%s' in cache view '%s' "
5995
 
                                      "failed: %s", target, view->name,
5996
 
                                      isc_result_totext(result));
5997
 
                }
5998
 
        }
5999
 
        if (flushed && found) {
6000
 
                if (viewname != NULL)
6001
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6002
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
6003
 
                                      "flushing name '%s' in cache view '%s' "
6004
 
                                      "succeeded", target, viewname);
6005
 
                else
6006
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6007
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
6008
 
                                      "flushing name '%s' in all cache views "
6009
 
                                      "succeeded", target);
6010
 
                result = ISC_R_SUCCESS;
6011
 
        } else {
6012
 
                if (!found)
6013
 
                        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6014
 
                                      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
6015
 
                                      "flushing name '%s' in cache view '%s' "
6016
 
                                      "failed: view not found", target,
6017
 
                                      viewname);
6018
 
                result = ISC_R_FAILURE;
6019
 
        }
6020
 
        isc_task_endexclusive(server->task);
6021
 
        return (result);
6022
 
}
6023
 
 
6024
 
isc_result_t
6025
 
ns_server_status(ns_server_t *server, isc_buffer_t *text) {
6026
 
        int zonecount, xferrunning, xferdeferred, soaqueries;
6027
 
        unsigned int n;
6028
 
        const char *ob = "", *cb = "", *alt = "";
6029
 
 
6030
 
        if (ns_g_server->version_set) {
6031
 
                ob = " (";
6032
 
                cb = ")";
6033
 
                if (ns_g_server->version == NULL)
6034
 
                        alt = "version.bind/txt/ch disabled";
6035
 
                else
6036
 
                        alt = ns_g_server->version;
6037
 
        }
6038
 
        zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
6039
 
        xferrunning = dns_zonemgr_getcount(server->zonemgr,
6040
 
                                           DNS_ZONESTATE_XFERRUNNING);
6041
 
        xferdeferred = dns_zonemgr_getcount(server->zonemgr,
6042
 
                                            DNS_ZONESTATE_XFERDEFERRED);
6043
 
        soaqueries = dns_zonemgr_getcount(server->zonemgr,
6044
 
                                          DNS_ZONESTATE_SOAQUERY);
6045
 
 
6046
 
        n = snprintf((char *)isc_buffer_used(text),
6047
 
                     isc_buffer_availablelength(text),
6048
 
                     "version: %s%s%s%s\n"
6049
 
#ifdef ISC_PLATFORM_USETHREADS
6050
 
                     "CPUs found: %u\n"
6051
 
                     "worker threads: %u\n"
6052
 
#endif
6053
 
                     "number of zones: %u\n"
6054
 
                     "debug level: %d\n"
6055
 
                     "xfers running: %u\n"
6056
 
                     "xfers deferred: %u\n"
6057
 
                     "soa queries in progress: %u\n"
6058
 
                     "query logging is %s\n"
6059
 
                     "recursive clients: %d/%d/%d\n"
6060
 
                     "tcp clients: %d/%d\n"
6061
 
                     "server is up and running",
6062
 
                     ns_g_version, ob, alt, cb,
6063
 
#ifdef ISC_PLATFORM_USETHREADS
6064
 
                     ns_g_cpus_detected, ns_g_cpus,
6065
 
#endif
6066
 
                     zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
6067
 
                     soaqueries, server->log_queries ? "ON" : "OFF",
6068
 
                     server->recursionquota.used, server->recursionquota.soft,
6069
 
                     server->recursionquota.max,
6070
 
                     server->tcpquota.used, server->tcpquota.max);
6071
 
        if (n >= isc_buffer_availablelength(text))
6072
 
                return (ISC_R_NOSPACE);
6073
 
        isc_buffer_add(text, n);
6074
 
        return (ISC_R_SUCCESS);
6075
 
}
6076
 
 
6077
 
static isc_result_t
6078
 
delete_keynames(dns_tsig_keyring_t *ring, char *target,
6079
 
                unsigned int *foundkeys)
6080
 
{
6081
 
        char namestr[DNS_NAME_FORMATSIZE];
6082
 
        isc_result_t result;
6083
 
        dns_rbtnodechain_t chain;
6084
 
        dns_name_t foundname;
6085
 
        dns_fixedname_t fixedorigin;
6086
 
        dns_name_t *origin;
6087
 
        dns_rbtnode_t *node;
6088
 
        dns_tsigkey_t *tkey;
6089
 
 
6090
 
        dns_name_init(&foundname, NULL);
6091
 
        dns_fixedname_init(&fixedorigin);
6092
 
        origin = dns_fixedname_name(&fixedorigin);
6093
 
 
6094
 
 again:
6095
 
        dns_rbtnodechain_init(&chain, ring->mctx);
6096
 
        result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
6097
 
                                        origin);
6098
 
        if (result == ISC_R_NOTFOUND) {
6099
 
                dns_rbtnodechain_invalidate(&chain);
6100
 
                return (ISC_R_SUCCESS);
6101
 
        }
6102
 
        if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
6103
 
                dns_rbtnodechain_invalidate(&chain);
6104
 
                return (result);
6105
 
        }
6106
 
 
6107
 
        for (;;) {
6108
 
                node = NULL;
6109
 
                dns_rbtnodechain_current(&chain, &foundname, origin, &node);
6110
 
                tkey = node->data;
6111
 
 
6112
 
                if (tkey != NULL) {
6113
 
                        if (!tkey->generated)
6114
 
                                goto nextkey;
6115
 
 
6116
 
                        dns_name_format(&tkey->name, namestr, sizeof(namestr));
6117
 
                        if (strcmp(namestr, target) == 0) {
6118
 
                                (*foundkeys)++;
6119
 
                                dns_rbtnodechain_invalidate(&chain);
6120
 
                                (void)dns_rbt_deletename(ring->keys,
6121
 
                                                         &tkey->name,
6122
 
                                                         ISC_FALSE);
6123
 
                                goto again;
6124
 
                        }
6125
 
                }
6126
 
 
6127
 
        nextkey:
6128
 
                result = dns_rbtnodechain_next(&chain, &foundname, origin);
6129
 
                if (result == ISC_R_NOMORE)
6130
 
                        break;
6131
 
                if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
6132
 
                        dns_rbtnodechain_invalidate(&chain);
6133
 
                        return (result);
6134
 
                }
6135
 
        }
6136
 
 
6137
 
        return (ISC_R_SUCCESS);
6138
 
}
6139
 
 
6140
 
isc_result_t
6141
 
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
6142
 
        isc_result_t result;
6143
 
        unsigned int n;
6144
 
        dns_view_t *view;
6145
 
        unsigned int foundkeys = 0;
6146
 
        char *target;
6147
 
        char *viewname;
6148
 
 
6149
 
        (void)next_token(&command, " \t");  /* skip command name */
6150
 
        target = next_token(&command, " \t");
6151
 
        if (target == NULL)
6152
 
                return (ISC_R_UNEXPECTEDEND);
6153
 
        viewname = next_token(&command, " \t");
6154
 
 
6155
 
        result = isc_task_beginexclusive(server->task);
6156
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
6157
 
        for (view = ISC_LIST_HEAD(server->viewlist);
6158
 
             view != NULL;
6159
 
             view = ISC_LIST_NEXT(view, link)) {
6160
 
                if (viewname == NULL || strcmp(view->name, viewname) == 0) {
6161
 
                        RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
6162
 
                        result = delete_keynames(view->dynamickeys, target,
6163
 
                                                 &foundkeys);
6164
 
                        RWUNLOCK(&view->dynamickeys->lock,
6165
 
                                 isc_rwlocktype_write);
6166
 
                        if (result != ISC_R_SUCCESS) {
6167
 
                                isc_task_endexclusive(server->task);
6168
 
                                return (result);
6169
 
                        }
6170
 
                }
6171
 
        }
6172
 
        isc_task_endexclusive(server->task);
6173
 
 
6174
 
        n = snprintf((char *)isc_buffer_used(text),
6175
 
                     isc_buffer_availablelength(text),
6176
 
                     "%d tsig keys deleted.\n", foundkeys);
6177
 
        if (n >= isc_buffer_availablelength(text))
6178
 
                return (ISC_R_NOSPACE);
6179
 
        isc_buffer_add(text, n);
6180
 
 
6181
 
        return (ISC_R_SUCCESS);
6182
 
}
6183
 
 
6184
 
static isc_result_t
6185
 
list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
6186
 
             unsigned int *foundkeys)
6187
 
{
6188
 
        char namestr[DNS_NAME_FORMATSIZE];
6189
 
        char creatorstr[DNS_NAME_FORMATSIZE];
6190
 
        isc_result_t result;
6191
 
        dns_rbtnodechain_t chain;
6192
 
        dns_name_t foundname;
6193
 
        dns_fixedname_t fixedorigin;
6194
 
        dns_name_t *origin;
6195
 
        dns_rbtnode_t *node;
6196
 
        dns_tsigkey_t *tkey;
6197
 
        unsigned int n;
6198
 
        const char *viewname;
6199
 
 
6200
 
        if (view != NULL)
6201
 
                viewname = view->name;
6202
 
        else
6203
 
                viewname = "(global)";
6204
 
 
6205
 
        dns_name_init(&foundname, NULL);
6206
 
        dns_fixedname_init(&fixedorigin);
6207
 
        origin = dns_fixedname_name(&fixedorigin);
6208
 
        dns_rbtnodechain_init(&chain, ring->mctx);
6209
 
        result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
6210
 
                                        origin);
6211
 
        if (result == ISC_R_NOTFOUND) {
6212
 
                dns_rbtnodechain_invalidate(&chain);
6213
 
                return (ISC_R_SUCCESS);
6214
 
        }
6215
 
        if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
6216
 
                dns_rbtnodechain_invalidate(&chain);
6217
 
                return (result);
6218
 
        }
6219
 
 
6220
 
        for (;;) {
6221
 
                node = NULL;
6222
 
                dns_rbtnodechain_current(&chain, &foundname, origin, &node);
6223
 
                tkey = node->data;
6224
 
 
6225
 
                if (tkey != NULL) {
6226
 
                        (*foundkeys)++;
6227
 
                        dns_name_format(&tkey->name, namestr, sizeof(namestr));
6228
 
                        if (tkey->generated) {
6229
 
                                dns_name_format(tkey->creator, creatorstr,
6230
 
                                                sizeof(creatorstr));
6231
 
                                n = snprintf((char *)isc_buffer_used(text),
6232
 
                                             isc_buffer_availablelength(text),
6233
 
                                             "view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n",
6234
 
                                             viewname, namestr, creatorstr);
6235
 
                        } else {
6236
 
                                n = snprintf((char *)isc_buffer_used(text),
6237
 
                                             isc_buffer_availablelength(text),
6238
 
                                             "view \"%s\"; type \"static\"; key \"%s\";\n",
6239
 
                                             viewname, namestr);
6240
 
                        }
6241
 
                        if (n >= isc_buffer_availablelength(text)) {
6242
 
                                dns_rbtnodechain_invalidate(&chain);
6243
 
                                return (ISC_R_NOSPACE);
6244
 
                        }
6245
 
                        isc_buffer_add(text, n);
6246
 
                }
6247
 
                result = dns_rbtnodechain_next(&chain, &foundname, origin);
6248
 
                if (result == ISC_R_NOMORE)
6249
 
                        break;
6250
 
                if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
6251
 
                        dns_rbtnodechain_invalidate(&chain);
6252
 
                        return (result);
6253
 
                }
6254
 
        }
6255
 
 
6256
 
        return (ISC_R_SUCCESS);
6257
 
}
6258
 
 
6259
 
isc_result_t
6260
 
ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
6261
 
        isc_result_t result;
6262
 
        unsigned int n;
6263
 
        dns_view_t *view;
6264
 
        unsigned int foundkeys = 0;
6265
 
 
6266
 
        result = isc_task_beginexclusive(server->task);
6267
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
6268
 
        for (view = ISC_LIST_HEAD(server->viewlist);
6269
 
             view != NULL;
6270
 
             view = ISC_LIST_NEXT(view, link)) {
6271
 
                RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
6272
 
                result = list_keynames(view, view->statickeys, text,
6273
 
                                       &foundkeys);
6274
 
                RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
6275
 
                if (result != ISC_R_SUCCESS) {
6276
 
                        isc_task_endexclusive(server->task);
6277
 
                        return (result);
6278
 
                }
6279
 
                RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
6280
 
                result = list_keynames(view, view->dynamickeys, text,
6281
 
                                       &foundkeys);
6282
 
                RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
6283
 
                if (result != ISC_R_SUCCESS) {
6284
 
                        isc_task_endexclusive(server->task);
6285
 
                        return (result);
6286
 
                }
6287
 
        }
6288
 
        isc_task_endexclusive(server->task);
6289
 
 
6290
 
        if (foundkeys == 0) {
6291
 
                n = snprintf((char *)isc_buffer_used(text),
6292
 
                             isc_buffer_availablelength(text),
6293
 
                             "no tsig keys found.\n");
6294
 
                if (n >= isc_buffer_availablelength(text))
6295
 
                        return (ISC_R_NOSPACE);
6296
 
                isc_buffer_add(text, n);
6297
 
        }
6298
 
 
6299
 
        return (ISC_R_SUCCESS);
6300
 
}
6301
 
 
6302
 
/*
6303
 
 * Act on a "sign" command from the command channel.
6304
 
 */
6305
 
isc_result_t
6306
 
ns_server_sign(ns_server_t *server, char *args) {
6307
 
        isc_result_t result;
6308
 
        dns_zone_t *zone = NULL;
6309
 
        dns_zonetype_t type;
6310
 
        isc_uint16_t keyopts;
6311
 
 
6312
 
        result = zone_from_args(server, args, &zone);
6313
 
        if (result != ISC_R_SUCCESS)
6314
 
                return (result);
6315
 
        if (zone == NULL)
6316
 
                return (ISC_R_UNEXPECTEDEND);   /* XXX: or do all zones? */
6317
 
 
6318
 
        type = dns_zone_gettype(zone);
6319
 
        if (type != dns_zone_master) {
6320
 
                dns_zone_detach(&zone);
6321
 
                return (DNS_R_NOTMASTER);
6322
 
        }
6323
 
 
6324
 
        keyopts = dns_zone_getkeyopts(zone);
6325
 
        if ((keyopts & DNS_ZONEKEY_ALLOW) != 0)
6326
 
                dns_zone_rekey(zone);
6327
 
        else
6328
 
                result = ISC_R_NOPERM;
6329
 
 
6330
 
        dns_zone_detach(&zone);
6331
 
        return (result);
6332
 
}
6333
 
 
6334
 
/*
6335
 
 * Act on a "freeze" or "thaw" command from the command channel.
6336
 
 */
6337
 
isc_result_t
6338
 
ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
6339
 
                 isc_buffer_t *text)
6340
 
{
6341
 
        isc_result_t result, tresult;
6342
 
        dns_zone_t *zone = NULL;
6343
 
        dns_zonetype_t type;
6344
 
        char classstr[DNS_RDATACLASS_FORMATSIZE];
6345
 
        char zonename[DNS_NAME_FORMATSIZE];
6346
 
        dns_view_t *view;
6347
 
        char *journal;
6348
 
        const char *vname, *sep;
6349
 
        isc_boolean_t frozen;
6350
 
        const char *msg = NULL;
6351
 
 
6352
 
        result = zone_from_args(server, args, &zone);
6353
 
        if (result != ISC_R_SUCCESS)
6354
 
                return (result);
6355
 
        if (zone == NULL) {
6356
 
                result = isc_task_beginexclusive(server->task);
6357
 
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
6358
 
                tresult = ISC_R_SUCCESS;
6359
 
                for (view = ISC_LIST_HEAD(server->viewlist);
6360
 
                     view != NULL;
6361
 
                     view = ISC_LIST_NEXT(view, link)) {
6362
 
                        result = dns_view_freezezones(view, freeze);
6363
 
                        if (result != ISC_R_SUCCESS &&
6364
 
                            tresult == ISC_R_SUCCESS)
6365
 
                                tresult = result;
6366
 
                }
6367
 
                isc_task_endexclusive(server->task);
6368
 
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6369
 
                              NS_LOGMODULE_SERVER, ISC_LOG_INFO,
6370
 
                              "%s all zones: %s",
6371
 
                              freeze ? "freezing" : "thawing",
6372
 
                              isc_result_totext(tresult));
6373
 
                return (tresult);
6374
 
        }
6375
 
        type = dns_zone_gettype(zone);
6376
 
        if (type != dns_zone_master) {
6377
 
                dns_zone_detach(&zone);
6378
 
                return (DNS_R_NOTMASTER);
6379
 
        }
6380
 
 
6381
 
        result = isc_task_beginexclusive(server->task);
6382
 
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
6383
 
        frozen = dns_zone_getupdatedisabled(zone);
6384
 
        if (freeze) {
6385
 
                if (frozen) {
6386
 
                        msg = "WARNING: The zone was already frozen.\n"
6387
 
                              "Someone else may be editing it or "
6388
 
                              "it may still be re-loading.";
6389
 
                        result = DNS_R_FROZEN;
6390
 
                }
6391
 
                if (result == ISC_R_SUCCESS) {
6392
 
                        result = dns_zone_flush(zone);
6393
 
                        if (result != ISC_R_SUCCESS)
6394
 
                                msg = "Flushing the zone updates to "
6395
 
                                      "disk failed.";
6396
 
                }
6397
 
                if (result == ISC_R_SUCCESS) {
6398
 
                        journal = dns_zone_getjournal(zone);
6399
 
                        if (journal != NULL)
6400
 
                                (void)isc_file_remove(journal);
6401
 
                }
6402
 
                if (result == ISC_R_SUCCESS)
6403
 
                        dns_zone_setupdatedisabled(zone, freeze);
6404
 
        } else {
6405
 
                if (frozen) {
6406
 
                        result = dns_zone_loadandthaw(zone);
6407
 
                        switch (result) {
6408
 
                        case ISC_R_SUCCESS:
6409
 
                        case DNS_R_UPTODATE:
6410
 
                                msg = "The zone reload and thaw was "
6411
 
                                      "successful.";
6412
 
                                result = ISC_R_SUCCESS;
6413
 
                                break;
6414
 
                        case DNS_R_CONTINUE:
6415
 
                                msg = "A zone reload and thaw was started.\n"
6416
 
                                      "Check the logs to see the result.";
6417
 
                                result = ISC_R_SUCCESS;
6418
 
                                break;
6419
 
                        }
6420
 
                }
6421
 
        }
6422
 
        isc_task_endexclusive(server->task);
6423
 
 
6424
 
        if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
6425
 
                isc_buffer_putmem(text, (const unsigned char *)msg,
6426
 
                                  strlen(msg) + 1);
6427
 
 
6428
 
        view = dns_zone_getview(zone);
6429
 
        if (strcmp(view->name, "_default") == 0 ||
6430
 
            strcmp(view->name, "_bind") == 0)
6431
 
        {
6432
 
                vname = "";
6433
 
                sep = "";
6434
 
        } else {
6435
 
                vname = view->name;
6436
 
                sep = " ";
6437
 
        }
6438
 
        dns_rdataclass_format(dns_zone_getclass(zone), classstr,
6439
 
                              sizeof(classstr));
6440
 
        dns_name_format(dns_zone_getorigin(zone),
6441
 
                        zonename, sizeof(zonename));
6442
 
        isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6443
 
                      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
6444
 
                      "%s zone '%s/%s'%s%s: %s",
6445
 
                      freeze ? "freezing" : "thawing",
6446
 
                      zonename, classstr, sep, vname,
6447
 
                      isc_result_totext(result));
6448
 
        dns_zone_detach(&zone);
6449
 
        return (result);
6450
 
}
6451
 
 
6452
 
#ifdef HAVE_LIBSCF
6453
 
/*
6454
 
 * This function adds a message for rndc to echo if named
6455
 
 * is managed by smf and is also running chroot.
6456
 
 */
6457
 
isc_result_t
6458
 
ns_smf_add_message(isc_buffer_t *text) {
6459
 
        unsigned int n;
6460
 
 
6461
 
        n = snprintf((char *)isc_buffer_used(text),
6462
 
                isc_buffer_availablelength(text),
6463
 
                "use svcadm(1M) to manage named");
6464
 
        if (n >= isc_buffer_availablelength(text))
6465
 
                return (ISC_R_NOSPACE);
6466
 
        isc_buffer_add(text, n);
6467
 
        return (ISC_R_SUCCESS);
6468
 
}
6469
 
#endif /* HAVE_LIBSCF */