zone_data.h 30.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef DATASRC_MEMORY_ZONE_DATA_H
#define DATASRC_MEMORY_ZONE_DATA_H 1

#include <util/memory_segment.h>

20
#include <dns/name.h>
21
#include <dns/rrclass.h>
22

23
24
25
26
27
28
#include <datasrc/memory/domaintree.h>
#include <datasrc/memory/rdataset.h>

#include <boost/interprocess/offset_ptr.hpp>
#include <boost/noncopyable.hpp>

29
30
#include <vector>

31
namespace isc {
JINMEI Tatuya's avatar
JINMEI Tatuya committed
32
33
34
35
namespace dns {
namespace rdata {
namespace generic {
class NSEC3PARAM;
36
class NSEC3;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
37
38
39
40
}
}
}

41
42
43
namespace datasrc {
namespace memory {

JINMEI Tatuya's avatar
JINMEI Tatuya committed
44
45
typedef DomainTree<RdataSet> ZoneTree;
typedef DomainTreeNode<RdataSet> ZoneNode;
46
typedef DomainTreeNodeChain<RdataSet> ZoneChain;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
/// \brief NSEC3 data for a DNS zone.
///
/// This class encapsulates a set of NSEC3 related data for a zone
/// that is signed with NSEC3 RRs.  Specifically, it contains hash
/// parameters as given in an NSEC3PARAM RDATA and all NSEC3 RRs of the zone.
///
/// The main concept of the class is generally the same as that of
/// \c ZoneData (see its description for details), but the related data
//// are encapsulated in a more straightforward way in this class.
///
/// The NSEC3 RRs (which should normally have RRSIGs) are stored in a
/// \c DomainTree object whose data type is (a list of) \c RdataSet.
/// This tree is expected to store NSEC3 RRs only, so the RR type of
/// \c RdataSet should be NSEC3.  But this class itself doesn't guarantee
62
/// this condition.  It's the caller's responsibility.
63
64
///
/// Read-only access to the tree is possible via the \c getNSEC3Tree() method.
65
66
67
68
69
70
/// Modifying the tree must be done by a specific method (in the initial
/// implementation, it's \c insertName().  There may be some more as we
/// see the need); the application cannot directly change the content of the
/// tree in an arbitrary way.  This class does not have a strong reason to be
/// that strict, but is defined this way mainly to be consistent with the
/// \c ZoneData class.
71
72
73
74
75
76
77
78
79
80
81
///
/// Most of the hash parameters are maintained in the form of straightforward
/// member variables, which can be directly referenced by the application.
/// The exception is the salt, which is encapsulated as opaque data
/// immediately following the main class object, and should be accessible
/// via the \c getSaltLen() and \c getSaltData() method.
///
/// \note The fact that the this class couples one set of hash parameters
/// and the set of NSEC3 RRs implicitly means a zone is assumed to have
/// only one set of NSEC3 parameters.  When we support multiple sets of
/// parameters the design should be revised accordingly.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
82
83
class NSEC3Data : boost::noncopyable {
public:
84
85
86
87
88
    /// \brief Allocate and construct \c NSEC3Data from NSEC3PARAM Rdata.
    ///
    /// The NSEC3 parameters are extracted and stored within the created
    /// \c NSEC3Data object.
    ///
89
90
91
92
93
94
95
96
97
    /// This method ensures there'll be no memory leak on exception.
    /// But addresses allocated from \c mem_sgmt could be relocated if
    /// \c util::MemorySegmentGrown is thrown; the caller or its upper layer
    /// must be aware of that possibility and update any such addresses
    /// accordingly.  On successful return, this method ensures there's no
    /// address relocation.
    ///
    /// \throw util::MemorySegmentGrown The memory segment has grown, possibly
    ///     relocating data.
98
99
100
101
    /// \throw std::bad_alloc Memory allocation fails.
    ///
    /// \param mem_sgmt A \c MemorySegment from which memory for the new
    /// \c NSEC3Data is allocated.
102
    /// \param zone_origin The zone origin.
103
104
    /// \param rdata An NSEC3PARAM RDATA that specifies the NSEC3 parameters
    /// to be stored.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
105
    static NSEC3Data* create(util::MemorySegment& mem_sgmt,
106
                             const dns::Name& zone_origin,
JINMEI Tatuya's avatar
JINMEI Tatuya committed
107
                             const dns::rdata::generic::NSEC3PARAM& rdata);
108
109
110
111
112
113

    /// \brief Allocate and construct \c NSEC3Data from NSEC3 Rdata.
    ///
    /// The NSEC3 hash parameters are extracted and stored within the created
    /// \c NSEC3Data object.
    ///
114
115
116
117
118
119
120
121
122
    /// This method ensures there'll be no memory leak on exception.
    /// But addresses allocated from \c mem_sgmt could be relocated if
    /// \c util::MemorySegmentGrown is thrown; the caller or its upper layer
    /// must be aware of that possibility and update any such addresses
    /// accordingly.  On successful return, this method ensures there's no
    /// address relocation.
    ///
    /// \throw util::MemorySegmentGrown The memory segment has grown, possibly
    ///     relocating data.
123
124
125
126
    /// \throw std::bad_alloc Memory allocation fails.
    ///
    /// \param mem_sgmt A \c MemorySegment from which memory for the new
    /// \c NSEC3Data is allocated.
127
    /// \param zone_origin The zone origin.
128
129
    /// \param rdata An NSEC3 RDATA that specifies the NSEC3 parameters
    /// to be stored.
130
    static NSEC3Data* create(util::MemorySegment& mem_sgmt,
131
                             const dns::Name& zone_origin,
132
                             const dns::rdata::generic::NSEC3& rdata);
133
134
135

    /// \brief Destruct and deallocate \c NSEC3Data.
    ///
136
    /// It releases all resources allocated for the internal NSEC3 name space
137
138
139
140
141
142
143
    /// including NSEC3 RdataSet.  It assumes \c RdataSets objects stored
    /// in the space were allocated using the same memory segment as
    /// \c mem_sgmt.  The caller must ensure this assumption.
    ///
    /// Note that an \c RRClass object must be passed to this method.
    /// It's necessary to destroy the stored \c RdataSet objects
    /// (see its class description).  This class doesn't hold this information;
144
    /// it's the caller's responsibility to associate an \c NSEC3Data
145
146
147
    /// class object with its expected RR class, and pass it to
    /// \c destroy().  (In practice, it will be passed via
    /// \c ZoneData::destroy().)
148
149
150
151
152
    ///
    /// \throw none
    ///
    /// \param mem_sgmt The \c MemorySegment that allocated memory for
    /// \c data.
153
    /// \param data A non-NULL pointer to a valid NSEC3Data object
154
155
156
157
    /// that was originally created by the \c create() method (the behavior
    /// is undefined if this condition isn't met).
    /// \param nsec3_class The RR class of the \c RdataSet stored in the NSEC3
    /// name space to be destroyed.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
158
159
160
    static void destroy(util::MemorySegment& mem_sgmt, NSEC3Data* data,
                        dns::RRClass nsec3_class);

161
162
163
private:
    // Domain tree for the Internal NSEC3 name space.  Access to it is
    // limited only via public methods.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
164
165
    const boost::interprocess::offset_ptr<ZoneTree> nsec3_tree_;
public:
166
167
168
    const uint8_t hashalg;      ///< Hash algorithm
    const uint8_t flags;        ///< NSEC3 parameter flags
    const uint16_t iterations;  ///< Hash iterations
169
170
    // For 64-bit machines there'll be padding space here, but since
    // only at most one instance (or a few in very rare cases) will be
JINMEI Tatuya's avatar
JINMEI Tatuya committed
171
172
    // created per zone, the overhead should be acceptable.

173
174
175
176
177
178
179
180
181
182
    /// \brief Return \c ZoneTree for the NSEC3 name space.
    ///
    /// \throw none
    const ZoneTree& getNSEC3Tree() const { return (*nsec3_tree_); }

    /// \brief Return the size of NSEC3 salt.
    ///
    /// \throw none
    ///
    /// The return value must be in the range between 0 and 255 (inclusive).
JINMEI Tatuya's avatar
JINMEI Tatuya committed
183
    size_t getSaltLen() const { return (*getSaltBuf()); }
184
185
186
187
188
189
190
191

    /// \brief Return a pointer to the salt data.
    ///
    /// \throw none
    ///
    /// The valid range is up to the \c getSaltLen() bytes from the
    /// returned value.  If \c getSaltLen() returns 0, the return value
    /// of this method is invalid and must not be used.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
192
193
    const uint8_t* getSaltData() const { return (getSaltBuf() + 1); }

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
    /// \brief Insert a name to the NSEC3 name space.
    ///
    /// It allocates resource for the given name in the internal NSEC3 name
    /// space, and returns an access point to it in the form of \c ZoneNode
    /// pointer via the given \c node variable.  If the name already exists
    /// in the name space, it returns a pointer to the existing node.
    ///
    /// This method does not perform any semantics check on the given name
    /// (e.g., whether the first label is a valid encoded string for an NSEC3
    /// owner name).
    ///
    /// \throw std::bad_alloc Memory allocation fails
    ///
    /// \param mem_sgmt Memory segment in which resource for the new memory
    /// is to be allocated.
    /// \param name The name to be inserted.
    /// \param node A pointer to \c ZoneNode pointer in which the created or
    /// found node for the name is stored.  Must not be NULL (the method does
    /// not check that condition).
213
214
215
    void insertName(util::MemorySegment& mem_sgmt, const dns::Name& name,
                    ZoneNode** node);

JINMEI Tatuya's avatar
JINMEI Tatuya committed
216
private:
217
    // Common subroutine for the public versions of create().
218
    static NSEC3Data* create(util::MemorySegment& mem_sgmt,
219
                             const dns::Name& zone_origin,
220
221
                             uint8_t hashalg, uint8_t flags,
                             uint16_t iterations,
222
223
                             const std::vector<uint8_t>& salt);

224
225
226
227
228
229
    /// \brief The constructor.
    ///
    /// An object of this class is always expected to be created by the
    /// allocator (\c create()), so the constructor is hidden as private.
    ///
    /// It never throws an exception.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    NSEC3Data(ZoneTree* nsec3_tree_param, uint8_t hashalg_param,
              uint8_t flags_param, uint16_t iterations_param) :
        nsec3_tree_(nsec3_tree_param), hashalg(hashalg_param),
        flags(flags_param), iterations(iterations_param)
    {}

    const uint8_t* getSaltBuf() const {
        return (reinterpret_cast<const uint8_t*>(this + 1));
    }
    uint8_t* getSaltBuf() {
        return (reinterpret_cast<uint8_t*>(this + 1));
    }
};

244
245
246
247
248
249
250
251
252
253
/// \brief DNS zone data.
///
/// This class encapsulates the content of a DNS zone (which is essentially a
/// set of RRs) in a memory efficient way and provides accessor interfaces
/// to it.
///
/// The primary goal of this class is to provide a packed structure of the
/// data for memory efficiency.  Basically, this class should be considered
/// a private part of some other classes within this module and should not
/// be used directly from normal applications.  So it's not intended to hide
254
255
/// much of the underlying implementation details; rather, it tries
/// to keep the representation simple.
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
///
/// The RRs are stored in a \c DomainTree object whose data type is
/// (a list of) \c RdataSet.  The tree nodes correspond to owner names,
/// and the \c RdataSet objects (forming a linked list) set in the node
/// represent the rest of the RR parameters except the RR class: type,
/// TTL, and RDATA.  This class does not have any knowledge of the RR class
/// of the zone; since it's quite likely that the application maintains
/// a set of zones of the same RR class, and the number of such zones can be
/// huge, it makes more sense to have the application maintain the class value
/// in a unified way to minimize memory footprint.
///
/// The \c DomainTree object in this class is not expected to hold NSEC3
/// RRs when the zone is signed with NSEC3; they should be maintained
/// in an associated \c NSEC3Data object.  But this class does not prevent
/// the unexpected usage of adding an NSEC3 RdataSet directly in the tree.
271
/// It's the caller's responsibility to ensure this assumption.
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
///
/// This class maintains some other meta data and additional zone related
/// content.  First, it automatically creates a \c DomainTree node for the
/// zone's origin name on initialization and keeps a reference to it
/// throughout its lifetime.  This is the case even if the zone doesn't have
/// any RRs (such as in the case before initial loading).  Any valid zone
/// to be served should have an RR at the origin node (at least SOA, for
/// example), so this assumption should be reasonable.  But the application
/// must ensure that any \c ZoneData object in actual use should have an
/// RR at the origin; otherwise the inconsistency between the internal state
/// and the actual zone content could lead to unexpected disruption.
/// In particular, it must be careful when it supports dynamic updates
/// to an existing zone so an update attempt doesn't result in deleting
/// the origin node.
///
287
/// To ensure integrity regarding the reference to the origin, write
288
289
290
291
/// access to the tree node can be done only by public methods; the member
/// variable for the tree is hidden as private.  On the other hand, read-only
/// access to the tree is allowed via the const version of \c getZoneTree()
/// method for the convenience of the application.  So, it's intentional
292
/// that there's no non-const version of this method.  Do not add one
293
294
295
296
/// when this class is to be extended.
///
/// Another type of meta data is parameters and records of NSEC3 RRs
/// when the zone is signed with NSEC3.  It's represented in the form of
297
298
/// an \c NSEC3Data object, and a \c ZoneData object may be associated with
/// 0 or 1 \c NSEC3Data objects using the \c setNSEC3Data() method, which
299
/// can be retrieved by the \c getNSEC3Data() method.  If the \c ZoneData
300
/// object is not associated with an \c NSEC3Data object, it's considered not
301
302
303
/// signed with NSEC3 RRs; otherwise it's considered to be signed with
/// NSEC3 RRs and with the parameters stored in the \c NSEC3Data object.
///
304
/// \note This interpretation may change in the future when we support migration
305
306
307
/// from NSEC to NSEC3 or vice versa, support incremental signing, or support
/// multiple sets of NSEC3 parameters.
///
308
/// One other type of meta data is the status of the zone in terms of DNSSEC
309
310
311
312
313
314
315
316
/// signing.  This class supports the following concepts:
/// - Whether the zone is signed or not, either with NSEC records or NSEC3
///   records.
/// - Whether the zone has a complete set of NSEC3 records.
///
/// The former status can be accessed via the \c isSigned() and \c setSigned()
/// methods; the latter can be retrieved via the \c isNSEC3Signed() method.
///
317
/// This class does not actually relate the status of signed-or-not to
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/// any of its other attributes; it's up to the application how to set or
/// use this status and maintain it in a reasonable way.  One possible
/// definition is to set this status if and only if the zone has a
/// DNSKEY RR at the zone origin (which is BIND 9's definition of signed
/// zone).  When the application adopts this definition, it's the
/// application's responsibility to keep the status consistent with the
/// actual existence or non-existence of a DNSKEY RR.
///
/// In the current implementation, a zone is considered to have a complete
/// set of NSEC3 records if and only if it's associated with an \c NSEC3Data
/// object (as noted above, these concepts may be separated in future).
/// For this reason there is no "set" method for the latter; setting
/// an \c NSEC3Data effectively enables the latter status.  \c isNSEC3Signed()
/// method is still provided (even though it's a kind of trivial wrapper to
/// \c getNSEC3Data()) partly for a more intuitive shortcut, and partly
/// because we won't have to change the application code when we implement
/// the future separation.
///
336
337
338
339
340
341
342
343
344
/// One last type of meta data is the zone's "minimum" TTL.  It's expected
/// to be a shortcut copy of the minimum field of the zone's SOA RDATA,
/// and is expected to be used to create an SOA RR for a negative response,
/// whose RR TTL may have to be set to this value according to RFC2308.
/// This class is not aware of such usage, however, and only provides a
/// simple getter and setter method for this value: \c getMinTTLData() and
/// \c setMinTTL().  The user of this class is responsible for setting the
/// value with \c setMinTTL() when it loads or updates the SOA RR.
///
345
346
347
348
349
350
351
352
353
354
/// The intended usage of these two status concepts is to implement the
/// \c ZoneFinder::Context::isNSECSigned() and
/// \c ZoneFinder::Context::isNSEC3Signed() methods.  A possible implementation
/// is as follows:
/// - \c ZoneFinder::Context::isNSECSigned() returns true iff \c isSigned()
///   is true and \c isNSEC3Signed() is false.
/// - \c ZoneFinder::Context::isNSEC3Signed() returns true iff \c isSigned()
///   is true and \c isNSEC3Signed() is true.
///
/// Note that even though \c isNSEC3Signed() being true should indicate
355
/// \c isSigned() is true too in practice, the interfaces do not
356
357
358
359
360
361
362
363
/// automatically ensure that, so we'd need to check both conditions
/// explicitly.  And, in fact, if we adopt the above definition of
/// \c isSigned(), it's possible that a zone has a complete set of NSEC3
/// RRs but no DNSKEY (although it's effectively a broken zone unless we
/// support incremental signing).
///
/// This class is designed so an instance can be stored in a shared
/// memory region.  So the pointer member variables (the initial
364
/// implementation only contains pointer member variables) are defined
365
/// as offset pointers.  When this class is extended these properties must
366
/// be preserved, and must also meet other requirements so it can be stored
367
368
369
370
/// in a shared memory region (see, for example, \c RdataSet description).
/// Future extensions must also be conscious of placing the member variables
/// so that they will not accidentally cause padding and increase memory
/// footprint.
371
class ZoneData : boost::noncopyable {
372
private:
373
374
375
376
377
378
    /// \brief The constructor.
    ///
    /// An object of this class is always expected to be created by the
    /// allocator (\c create()), so the constructor is hidden as private.
    ///
    /// It never throws an exception.
379
    ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node);
380

381
382
383
384
    // Zone node flags.  When adding a new flag, it's generally advisable to
    // keep existing values so the binary image of the data is as much
    // backward compatible as possible.  And it can be helpful in practice
    // for file-mapped data.
385
386
387
388
389
private:
    // Set in the origin node (which always exists at the same address)
    // to indicate whether the zone is signed or not.  Internal use,
    // so defined as private.
    static const ZoneNode::Flags DNSSEC_SIGNED = ZoneNode::FLAG_USER1;
390

391
392
393
394
public:
    /// \brief Node flag indicating it is at a "wildcard level"
    ///
    /// This means one of the node's immediate children is a wildcard.
395
396
397
398
399
400
401
    static const ZoneNode::Flags WILDCARD_NODE = ZoneNode::FLAG_USER2;

private:
    // Also set in the origin node, indicating this is a special "empty zone",
    // that could be created only by the corresponding create() method to be
    // used for some kind of sentinel data.
    static const ZoneNode::Flags EMPTY_ZONE = ZoneNode::FLAG_USER3;
402

403
public:
404
405
    /// \brief Allocate and construct \c ZoneData.
    ///
406
407
408
409
410
411
412
413
414
    /// This method ensures there'll be no memory leak on exception.
    /// But addresses allocated from \c mem_sgmt could be relocated if
    /// \c util::MemorySegmentGrown is thrown; the caller or its upper layer
    /// must be aware of that possibility and update any such addresses
    /// accordingly.  On successful return, this method ensures there's no
    /// address relocation.
    ///
    /// \throw util::MemorySegmentGrown The memory segment has grown, possibly
    ///     relocating data.
415
416
417
418
    /// \throw std::bad_alloc Memory allocation fails.
    ///
    /// \param mem_sgmt A \c MemorySegment from which memory for the new
    /// \c ZoneData is allocated.
419
    /// \param zone_origin The zone origin.
420
    static ZoneData* create(util::MemorySegment& mem_sgmt,
421
                            const dns::Name& zone_origin);
422

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
    /// \brief Allocate and construct a special "empty" \c ZoneData.
    ///
    /// A ZoneData object created this way holds all internal integrity
    /// that those created by the other \c create() method have, but is not
    /// publicly associated with any actual zone data.  It's intended to be
    /// used as a kind of sentinel data to representing the concept such as
    /// "broken zone".
    ///
    /// Methods calls on empty \c ZoneData object except \c destroy() and
    /// \c isEmpty() are meaningless, while they shouldn't cause disruption.
    /// It's caller's responsibility to use empty zone data objects in the
    /// intended way.
    ///
    /// \param mem_sgmt A \c MemorySegment from which memory for the new
    /// \c ZoneData is allocated.
    static ZoneData* create(util::MemorySegment& mem_sgmt);

440
441
442
443
444
445
446
447
448
    /// \brief Destruct and deallocate \c ZoneData.
    ///
    /// It releases all resource allocated in the internal storage NSEC3 for
    /// zone names and RdataSet objects, and if associated, the \c NSEC3Data.
    /// It assumes \c RdataSets objects stored in the space and the
    /// associated \c NSEC3Data object were allocated using the same memory
    /// segment as \c mem_sgmt.  The caller must ensure this assumption.
    ///
    /// Note that an \c RRClass object must be passed to this method.
449
    /// It's used to destroy the stored \c RdataSet objects
450
    /// (see its class description).  This class doesn't hold this information;
451
452
    /// it's the caller's responsibility to associate a \c ZoneData class
    /// object with its expected RR class, and pass it to \c destroy().
453
454
455
456
457
    ///
    /// \throw none
    ///
    /// \param mem_sgmt The \c MemorySegment that allocated memory for
    /// \c zone_data.
458
    /// \param zone_data A non-NULL pointer to a valid ZoneData object
459
460
461
462
463
464
    /// that was originally created by the \c create() method (the behavior
    /// is undefined if this condition isn't met).
    /// \param zone_class The RR class of the \c RdataSet stored in the
    /// internal tree.
    static void destroy(util::MemorySegment& mem_sgmt, ZoneData* zone_data,
                        dns::RRClass zone_class);
465

466
467
468
469
    ///
    /// \name Getter methods
    ///
    //@{
470
471
472
473
474
475
    /// \brief Return zone's origin node.
    ///
    /// This is a convenience and efficient short cut to get access to the
    /// zone origin in the form of \c ZoneNode object.
    ///
    /// The class encapsulation ensures that the origin node always exists at
476
    /// the same address, so this method always returns a non-NULL valid
477
    /// pointer.
478
479
    ///
    /// \throw none
480
481
482
    const ZoneNode* getOriginNode() const {
        return (origin_node_.get());
    }
483

484
485
    /// \brief Return the zone's name space in the form of \c ZoneTree
    ///
486
    /// \note It's intentional that non-const version of this method
487
488
489
490
491
492
493
494
495
496
497
498
499
    /// isn't provided.  See the class description.
    ///
    /// \throw none
    const ZoneTree& getZoneTree() const { return (*zone_tree_); }

    /// \brief Return whether or not the zone is signed in terms of DNSSEC.
    ///
    /// Note that this class does not care about what "signed" means.
    /// This method simply returns the last value set by \c setSigned()
    /// (or the default, which is \c false).  The caller is expected to
    /// use this method and \c setSigned() in a reasonable, consistent way.
    ///
    /// \throw none
500
501
    bool isSigned() const { return (origin_node_->getFlag(DNSSEC_SIGNED)); }

502
503
    /// \brief Return whether or not the zone is signed with NSEC3 RRs.
    ///
504
    /// In the current implementation, the zone is considered signed with
505
    /// NSEC3 if and only if it has non-NULL NSEC3 data.
506
507
    ///
    /// This also means it's not considered NSEC3 signed by default.
508
509
    ///
    /// \throw none
510
511
    bool isNSEC3Signed() const { return (nsec3_data_); }

512
513
514
515
516
517
518
    /// \brief Return whether or not the zone data is "empty".
    ///
    /// See the description of \c create() for the concept of empty zone data.
    ///
    /// \throw None
    bool isEmpty() const { return (origin_node_->getFlag(EMPTY_ZONE)); }

519
520
    /// \brief Return NSEC3Data of the zone.
    ///
521
    /// This method returns non-NULL valid pointer to \c NSEC3Data object
522
523
524
525
    /// associated to the \c ZoneData if it was set by \c setNSEC3Data();
    /// otherwise it returns NULL.
    ///
    /// \throw none
JINMEI Tatuya's avatar
JINMEI Tatuya committed
526
    const NSEC3Data* getNSEC3Data() const { return (nsec3_data_.get()); }
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546

    /// \brief Return a pointer to the zone's minimum TTL data.
    ///
    /// The returned pointer points to a memory region that is valid at least
    /// for 32 bits, storing the zone's minimum TTL in the network byte
    /// order.  The corresponding 32-bit value as an integer is initially
    /// set to the value of \c dns::RRTTL::MAX_TTL(), and, once
    /// \c setMinTTL() is called, set to the value specified at the latest
    /// call to \c setMinTTL().
    ///
    /// It returns opaque data to make it clear that unless the wire
    /// format data is necessary (e.g., when rendering it in a DNS message),
    /// it should be converted to, e.g., an \c RRTTL object explicitly.
    ///
    /// The returned pointer is valid as long as the \c ZoneData is valid,
    /// and the corresponding 32-bit data are the same until \c setMinTTL()
    /// is called.
    ///
    /// \throw none
    const void* getMinTTLData() const { return (&min_ttl_); }
547
    //@}
548

549
550
551
552
    ///
    /// \name Methods for modifying the tree
    ///
    //@{
553
554
555
556
557
558
559
560
561
    /// \brief Insert a name to the zone.
    ///
    /// It allocates resource for the given name in the internal storage
    /// for zone data, and returns an access point to it in the form of
    /// \c ZoneNode pointer via the given \c node variable.  If the name
    /// already exists in the name space, it returns a pointer to the existing
    /// node.
    ///
    /// The name to be inserted by this method is expected to belong to
562
    /// zone's "normal" (i.e., non-NSEÇ3) name space.  If it's a name for
563
564
565
566
    /// an NSEC3 RR, it must be set in the corresponding \c NSEC3Data for
    /// this zone data (if it doesn't exist it must be created and set
    /// by \c setNSEC3Data()).
    ///
567
    /// The name is also expected to be a subdomain of, or equal to the
568
569
570
571
    /// zone's origin name (specified on creation in \c create()), but
    /// this method does not check that condition.  The caller is responsible
    /// for ensuring this assumption.
    ///
572
573
574
    /// Since this method doesn't perform any semantics check, it always
    /// succeeds (except for the rare case where memory allocation
    /// fails) and \c node will be set to a valid pointer.
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
    ///
    /// \note We may want to differentiate between the case where the name is
    /// newly created and the case where it already existed.  Right now it's
    /// unclear, so it doesn't return this information.  If we see the need
    /// for it, this method can be extended that way.
    ///
    /// \throw std::bad_alloc Memory allocation fails
    ///
    /// \param mem_sgmt Memory segment in which resource for the new memory
    /// is to be allocated.
    /// \param name The name to be inserted.
    /// \param node A pointer to \c ZoneNode pointer in which the created or
    /// found node for the name is stored.  Must not be NULL (the method does
    /// not check that condition).
    void insertName(util::MemorySegment& mem_sgmt, const dns::Name& name,
                    ZoneNode** node);

    /// \brief Specify whether or not the zone is signed in terms of DNSSEC.
    ///
    /// The zone will be considered "signed" (in that subsequent calls to
    /// \c isSigned() will return \c true) iff the parameter \c on is \c true.
    ///
    /// This class does not care what "signed" actually means; it does not
598
    /// check any zone RRs to verify if the given state makes sense (e.g.
599
600
601
602
603
604
605
606
607
    /// whether the zone has a DNSKEY RR at the origin).  The caller is
    /// expected to use this method and \c isSigned() in a reasonable,
    /// consistent way.
    ///
    /// \throw none
    void setSigned(bool on) {
        origin_node_->setFlag(DNSSEC_SIGNED, on);
    }

608
    /// \brief Return NSEC3Data of the zone, non-const version.
609
    ///
610
    /// This is similar to the const version, but return a non-const pointer
611
612
613
    /// so the caller can modify the content.
    ///
    /// \throw none
JINMEI Tatuya's avatar
JINMEI Tatuya committed
614
    NSEC3Data* getNSEC3Data() { return (nsec3_data_.get()); }
615
616
617
618
619
620
621
622
623

    /// \brief Associate \c NSEC3Data to the zone.
    ///
    /// This method associates the given \c NSEC3Data object with the zone
    /// data.  If there was already associated \c NSEC3Data object, it will
    /// be returned.  If no \c NSEC3Data object was associated before,
    /// a NULL pointer will be returned.  \c nsec3_data can be NULL, in which
    /// case the zone will be disassociated with a \c NSEC3Data.
    ///
624
    /// In general, if a non-NULL pointer is passed, it's assumed that
625
626
627
628
629
630
631
632
633
634
635
636
637
    /// the \c NSEC3Data object was allocated in the same \c MemorySegment
    /// as that for the zone data, so the \c destroy() method can destroy
    /// both with the same memory segment.  If this condition is not met,
    /// the caller must extract the associated \c NSEC3Data by calling
    /// this method with NULL and release any resource for it by itself
    /// before destroying this zone data.
    ///
    /// \throw none
    ///
    /// \param nsec3_data A pointer to \c NSEC3Data object to be associated
    /// with the zone.  Can be NULL.
    /// \return Previously associated \c NSEC3Data object in the zone.  This
    /// can be NULL.
JINMEI Tatuya's avatar
JINMEI Tatuya committed
638
639
640
641
642
    NSEC3Data* setNSEC3Data(NSEC3Data* nsec3_data) {
        NSEC3Data* old = nsec3_data_.get();
        nsec3_data_ = nsec3_data;
        return (old);
    }
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661

    /// \brief Set the zone's "minimum" TTL.
    ///
    /// This method updates the recorded minimum TTL of the zone data.
    /// It's expected to be identical to the value of the Minimum field
    /// of the SOA RR at the zone apex, but this method does not check the
    /// consistency; it's the caller's responsibility.
    ///
    /// While RFC2181 specifies the max TTL value to be 2^31-1, this method
    /// does not check the range; it accepts any unsigned 32-bit integer
    /// value.  In practice, this shouldn't cause a problem, however, because
    /// the only expected usage of this value is to use the minimum of this
    /// value and SOA RR's TTL, and the latter is expected to be in the
    /// valid range.
    ///
    /// \throw None
    /// \param min_ttl_val The minimum TTL value as unsigned 32-bit integer
    /// in the host byte order.
    void setMinTTL(uint32_t min_ttl_val);
662
    //@}
JINMEI Tatuya's avatar
JINMEI Tatuya committed
663

664
665
666
private:
    const boost::interprocess::offset_ptr<ZoneTree> zone_tree_;
    const boost::interprocess::offset_ptr<ZoneNode> origin_node_;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
667
    boost::interprocess::offset_ptr<NSEC3Data> nsec3_data_;
668
    uint32_t min_ttl_;
669
670
671
672
673
674
675
676
677
678
679
};

} // namespace memory
} // namespace datasrc
} // namespace isc

#endif // DATASRC_MEMORY_ZONE_DATA_H

// Local Variables:
// mode: c++
// End: