Branch data Line data Source code
1 : : // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #ifndef __MASTERLOAD_H
16 : : #define __MASTERLOAD_H 1
17 : :
18 : : #include <iosfwd>
19 : :
20 : : #include <boost/function.hpp>
21 : :
22 : : #include <exceptions/exceptions.h>
23 : :
24 : : #include <dns/rrset.h>
25 : :
26 : : namespace isc {
27 : : namespace dns {
28 : : class Name;
29 : : class RRClass;
30 : :
31 : : /// \brief An exception that is thrown if an error occurs while loading a
32 : : /// master zone data.
33 : 24 : class MasterLoadError : public isc::Exception {
34 : : public:
35 : 22 : MasterLoadError(const char* file, size_t line, const char* what) :
36 [ + - ]: 24 : isc::Exception(file, line, what) {}
37 : : };
38 : :
39 : : /// The type of the \c callback parameter of \c masterLoad().
40 : : ///
41 : : /// This represents a functor object or a function that takes one parameter
42 : : /// of type \c RRsetPtr and returns nothing.
43 : : typedef boost::function<void(RRsetPtr)> MasterLoadCallback;
44 : :
45 : : ///
46 : : /// \name Master zone file loader functions.
47 : : ///
48 : : //@{
49 : : /// Master zone file loader from a file.
50 : : ///
51 : : /// This function parses a given file as a master DNS zone file for
52 : : /// the given origin name and RR class, constructs a sequence of \c RRset
53 : : /// from the RRs containing in the file, and calls the given \c callback
54 : : /// functor object or function with each \c RRset.
55 : : ///
56 : : /// The \c callback parameter is a functor object or a function that
57 : : /// takes one parameter of type \c RRsetPtr and returns nothing,
58 : : /// i.e. \c void (see below for specific examples).
59 : : /// More precisely, it can be anything that this form of boost::function
60 : : /// can represent, but the caller normally doesn't have to care about
61 : : /// that level of details.
62 : : ///
63 : : /// The ownership of constructed RRsets is transferred to the callback
64 : : /// and this function never uses it once it is called.
65 : : /// The callback can freely modify the passed \c RRset.
66 : : ///
67 : : /// This function performs minimum level of validation on the input:
68 : : /// - Each RR is a valid textual representation per the DNS protocol.
69 : : /// - The class of each RR must be identical to the specified RR class.
70 : : /// - The owner name of each RR must be a subdomain of the origin name
71 : : /// (that can be equal to the origin).
72 : : /// - If an SOA RR is included, its owner name must be the origin name.
73 : : /// If any of these validation checks fails, this function throws an
74 : : /// exception of class \c MasterLoadError.
75 : : ///
76 : : /// It does not perform other semantical checks, however. For example,
77 : : /// it doesn't check if an NS RR of the origin name is included or if
78 : : /// there is more than one SOA RR. Such further checks are the caller's
79 : : /// (or the callback's) responsibility.
80 : : ///
81 : : /// <b>Acceptable Format</b>
82 : : ///
83 : : /// The current implementation only supports a restricted form of master files
84 : : /// for simplicity. One easy way to ensure that a handwritten zone file is
85 : : /// acceptable to this implementation is to preprocess it with BIND 9's
86 : : /// named-compilezone tool with both the input and output formats being
87 : : /// "text".
88 : : /// Here is an example:
89 : : /// \code % named-compilezone -f text -F text -o example.com.norm
90 : : /// example.com example.com.zone
91 : : /// \endcode
92 : : /// where example.com.zone is the original zone file for the "example.com"
93 : : /// zone. The output file is example.com.norm, which should be acceptable
94 : : /// by this implementation.
95 : : ///
96 : : /// Below are specific restrictions that this implementation assumes.
97 : : /// Basically, each RR must consist of exactly one line
98 : : /// (so there shouldn't be a multi-line RR) in the following format:
99 : : /// \code <owner name> <TTL> <RRCLASS> <RRTYPE> <RDATA (single line)>
100 : : /// \endcode
101 : : /// Here are some more details about the restrictions:
102 : : /// - No special directives such as $TTL are supported.
103 : : /// - The owner name must be absolute, that is, it must end with a period.
104 : : /// - "@" is not recognized as a valid owner name.
105 : : /// - Owner names, TTL and RRCLASS cannot be omitted.
106 : : /// - As a corollary, a non blank line must not begin with a space character.
107 : : /// - The order of the RR parameters is fixed, for example, this is acceptable:
108 : : /// \code example.com. 3600 IN A 192.0.2.1
109 : : /// \endcode
110 : : /// but this is not even though it's valid per RFC1035:
111 : : /// \code example.com. IN 3600 A 192.0.2.1
112 : : /// \endcode
113 : : /// - "TTL", "RRCLASS", and "RRTYPE" must be recognizable by the \c RRTTL,
114 : : /// RRClass and RRType class implementations of this library. In particular,
115 : : /// as of this writing TTL must be a decimal number (a convenient extension
116 : : /// such as "1H" instead of 3600 cannot be used). Not all standard RR
117 : : /// classes and RR types are supported yet, so the mnemonics of them will
118 : : /// be rejected, too.
119 : : /// - RR TTLs of the same RRset must be the same; even if they are different,
120 : : /// this implementation simply uses the TTL of the first RR.
121 : : ///
122 : : /// Blank lines and lines beginning with a semi-colon are allowed, and will
123 : : /// be simply ignored. Comments cannot coexist with an RR line, however.
124 : : /// For example, this will be rejected:
125 : : /// \code example.com. 3600 IN A 192.0.2.1 ; this is a comment
126 : : /// \endcode
127 : : ///
128 : : /// This implementation assumes that RRs of a single RRset are not
129 : : /// interleaved with RRs of a different RRset.
130 : : /// That is, the following sequence shouldn't happen:
131 : : /// \code example.com. 3600 IN A 192.0.2.1
132 : : /// example.com. 3600 IN AAAA 2001:db8::1
133 : : /// example.com. 3600 IN A 192.0.2.2
134 : : /// \endcode
135 : : /// But it does not consider this an error; it will simply regard each RR
136 : : /// as a separate RRset and call the callback with them separately.
137 : : /// It is up to the callback to merge multiple RRsets into one if possible
138 : : /// and necessary.
139 : : ///
140 : : /// <b>Exceptions</b>
141 : : ///
142 : : /// This function throws an exception of class \c MasterLoadError in the
143 : : /// following cases:
144 : : /// - Any of the validation checks fails (see the class description).
145 : : /// - The input data is not in the acceptable format (see the details of
146 : : /// the format above).
147 : : /// - The specified file cannot be opened for loading.
148 : : /// - An I/O error occurs during the loading.
149 : : ///
150 : : /// In addition, this function requires resource allocation for parsing and
151 : : /// constructing RRsets. If it fails, the corresponding standard exception
152 : : /// will be thrown.
153 : : ///
154 : : /// The callback may throw its own function. This function doesn't catch it
155 : : /// and will simply propagate it towards the caller.
156 : : ///
157 : : /// <b>Usage Examples</b>
158 : : ///
159 : : /// A simplest example usage of this function would be to parse a zone
160 : : /// file and (after validation) dump the content to the standard output.
161 : : /// This is an example functor object and a call to \c masterLoad
162 : : /// that implements this scenario:
163 : : /// \code struct ZoneDumper {
164 : : /// void operator()(ConstRRsetPtr rrset) const {
165 : : /// std::cout << *rrset;
166 : : /// }
167 : : /// };
168 : : /// ...
169 : : /// masterLoad(zone_file, Name("example.com"), RRClass::IN(), ZoneDumper());
170 : : /// \endcode
171 : : /// Alternatively, you can use a normal function instead of a functor:
172 : : /// \code void zoneDumper(ConstRRsetPtr rrset) {
173 : : /// std::cout << *rrset;
174 : : /// }
175 : : /// ...
176 : : /// masterLoad(zone_file, Name("example.com"), RRClass::IN(), zoneDumper);
177 : : /// \endcode
178 : : /// Or, if you want to use it with a member function of some other class,
179 : : /// wrapping things with \c boost::bind would be handy:
180 : : /// \code class ZoneDumper {
181 : : /// public:
182 : : /// void dump(ConstRRsetPtr rrset) const {
183 : : /// std::cout << *rrset;
184 : : /// }
185 : : /// };
186 : : /// ...
187 : : /// ZoneDumper dumper;
188 : : /// masterLoad(rr_stream, Name("example.com"), RRClass::IN(),
189 : : /// boost::bind(&ZoneDumper::dump, &dumper, _1));
190 : : /// \endcode
191 : : /// You can find a bit more complicated examples in the unit tests code for
192 : : /// this function.
193 : : ///
194 : : /// <b>Implementation Notes</b>
195 : : ///
196 : : /// The current implementation is in a preliminary level and needs further
197 : : /// extensions. Some design decisions may also have to be reconsidered as
198 : : /// we gain experiences. Those include:
199 : : /// - We should be more flexible about the input format.
200 : : /// - We may want to allow optional conditions. For example, we may want to
201 : : /// be generous about some validation failures and be able to continue
202 : : /// parsing.
203 : : /// - Especially if we allow to be generous, we may also want to support
204 : : /// returning an error code instead of throwing an exception when we
205 : : /// encounter validation failure.
206 : : /// - We may want to support incremental loading.
207 : : /// - If we add these optional features we may want to introduce a class
208 : : /// that encapsulates loading status and options.
209 : : /// - RRSIGs are handled as separate RRsets, i.e. they are not included in
210 : : /// the RRset they cover.
211 : : ///
212 : : /// \param filename A path to a master zone file to be loaded.
213 : : /// \param origin The origin name of the zone.
214 : : /// \param zone_class The RR class of the zone.
215 : : /// \param callback A callback functor or function that is to be called
216 : : /// for each RRset.
217 : : void masterLoad(const char* const filename, const Name& origin,
218 : : const RRClass& zone_class, MasterLoadCallback callback);
219 : :
220 : : /// Master zone file loader from input stream.
221 : : ///
222 : : /// This function is same as the other version
223 : : /// (\c masterLoad(const char* const, const Name&, const RRClass&, MasterLoadCallback))
224 : : /// except that it takes a \c std::istream instead of a file.
225 : : /// It extracts lines from the stream and handles each line just as a line
226 : : /// of a file for the other version of function.
227 : : /// All descriptions of the other version apply to this version except those
228 : : /// specific to file I/O.
229 : : ///
230 : : /// \param input An input stream object that is to emit zone's RRs.
231 : : /// \param origin The origin name of the zone.
232 : : /// \param zone_class The RR class of the zone.
233 : : /// \param callback A callback functor or function that is to be called for
234 : : /// each RRset.
235 : : void masterLoad(std::istream& input, const Name& origin,
236 : : const RRClass& zone_class, MasterLoadCallback callback);
237 : : }
238 : : //@}
239 : : }
240 : :
241 : : #endif // __MASTERLOAD_H
242 : :
243 : : // Local Variables:
244 : : // mode: c++
245 : : // End:
|