Branch data Line data Source code
1 : : ///////////////
2 : : ///////////////
3 : : /////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
4 : : /////////////// DO NOT EDIT!
5 : : ///////////////
6 : : ///////////////
7 : :
8 : : // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
9 : : //
10 : : // Permission to use, copy, modify, and/or distribute this software for any
11 : : // purpose with or without fee is hereby granted, provided that the above
12 : : // copyright notice and this permission notice appear in all copies.
13 : : //
14 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
17 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
19 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 : : // PERFORMANCE OF THIS SOFTWARE.
21 : :
22 : : #include <cassert>
23 : : #include <algorithm>
24 : : #include <cctype>
25 : : #include <functional>
26 : : #include <map>
27 : : #include <string>
28 : : #include <sstream>
29 : : #include <utility>
30 : :
31 : : #include <stdint.h>
32 : :
33 : : #include <boost/shared_ptr.hpp>
34 : :
35 : : #include <exceptions/exceptions.h>
36 : :
37 : : #include <dns/rrparamregistry.h>
38 : : #include <dns/rrclass.h>
39 : : #include <dns/rrtype.h>
40 : : #include <dns/rdata.h>
41 : : #include <dns/rdataclass.h>
42 : :
43 : : using namespace std;
44 : : using namespace boost;
45 : :
46 : : using namespace isc::util;
47 : : using namespace isc::dns::rdata;
48 : :
49 : : namespace isc {
50 : : namespace dns {
51 : : namespace {
52 : : ///
53 : : /// The following function and class are a helper to define case-insensitive
54 : : /// equivalence relationship on strings. They are used in the mapping
55 : : /// containers below.
56 : : ///
57 : : bool
58 : 873975 : CICharLess(char c1, char c2) {
59 : 873975 : return (tolower(static_cast<unsigned char>(c1)) <
60 : 873975 : tolower(static_cast<unsigned char>(c2)));
61 : : }
62 : :
63 : : struct CIStringLess :
64 : : public binary_function<string, string, bool>
65 : : {
66 : 251540 : bool operator()(const string& s1, const string& s2) const
67 : : {
68 : : return (lexicographical_compare(s1.begin(), s1.end(),
69 : 251540 : s2.begin(), s2.end(), CICharLess));
70 : : }
71 : : };
72 : :
73 : 731 : struct RRTypeParam {
74 : : RRTypeParam(const string& code_string, uint16_t code) :
75 [ + - ]: 731 : code_string_(code_string), code_(code) {}
76 : : string code_string_;
77 : : uint16_t code_;
78 : :
79 : : /// magic constants
80 : : static const unsigned int MAX_CODE = 0xffff;
81 : : static const string& UNKNOWN_PREFIX();
82 : : static size_t UNKNOWN_PREFIXLEN();
83 : : static const string& UNKNOWN_MAX();
84 : : static size_t UNKNOWN_MAXLEN();
85 : : };
86 : :
87 : : typedef boost::shared_ptr<RRTypeParam> RRTypeParamPtr;
88 : : typedef map<string, RRTypeParamPtr, CIStringLess> StrRRTypeMap;
89 : : typedef map<uint16_t, RRTypeParamPtr> CodeRRTypeMap;
90 : :
91 : : inline const string&
92 : 856 : RRTypeParam::UNKNOWN_PREFIX() {
93 [ + + ][ + - ]: 856 : static const string p("TYPE");
[ + - ]
94 : 856 : return (p);
95 : : }
96 : :
97 : : inline size_t
98 : 429 : RRTypeParam::UNKNOWN_PREFIXLEN() {
99 [ + + ][ + - ]: 429 : static size_t plen = UNKNOWN_PREFIX().size();
[ + - ]
100 : 429 : return (plen);
101 : : }
102 : :
103 : : inline const string&
104 : : RRTypeParam::UNKNOWN_MAX() {
105 [ + - ][ + - ]: 7 : static const string p("TYPE65535");
[ + - ]
106 : : return (p);
107 : : }
108 : :
109 : : inline size_t
110 : : RRTypeParam::UNKNOWN_MAXLEN() {
111 [ + + ][ + - ]: 120 : static size_t plen = UNKNOWN_MAX().size();
112 : 113 : return (plen);
113 : : }
114 : :
115 : 110 : struct RRClassParam {
116 : : RRClassParam(const string& code_string, uint16_t code) :
117 [ + - ]: 110 : code_string_(code_string), code_(code) {}
118 : : string code_string_;
119 : : uint16_t code_;
120 : :
121 : : /// magic constants
122 : : static const unsigned int MAX_CODE = 0xffff;
123 : : static const string& UNKNOWN_PREFIX();
124 : : static size_t UNKNOWN_PREFIXLEN();
125 : : static const string& UNKNOWN_MAX();
126 : : static size_t UNKNOWN_MAXLEN();
127 : : };
128 : :
129 : : typedef boost::shared_ptr<RRClassParam> RRClassParamPtr;
130 : : typedef map<string, RRClassParamPtr, CIStringLess> StrRRClassMap;
131 : : typedef map<uint16_t, RRClassParamPtr> CodeRRClassMap;
132 : :
133 : : inline const string&
134 : 26 : RRClassParam::UNKNOWN_PREFIX() {
135 [ + + ][ + - ]: 26 : static const string p("CLASS");
[ + - ]
136 : 26 : return (p);
137 : : }
138 : :
139 : : inline size_t
140 : 60 : RRClassParam::UNKNOWN_PREFIXLEN() {
141 [ + + ][ + - ]: 60 : static size_t plen = UNKNOWN_PREFIX().size();
[ + - ]
142 : 60 : return (plen);
143 : : }
144 : :
145 : : inline const string&
146 : : RRClassParam::UNKNOWN_MAX() {
147 [ + - ][ + - ]: 5 : static const string p("CLASS65535");
[ + - ]
148 : : return (p);
149 : : }
150 : :
151 : : inline size_t
152 : : RRClassParam::UNKNOWN_MAXLEN() {
153 [ + + ][ + - ]: 23 : static size_t plen = UNKNOWN_MAX().size();
154 : 18 : return (plen);
155 : : }
156 : : } // end of anonymous namespace
157 : :
158 : : /// Note: the element ordering in the type/class pair is intentional.
159 : : /// The standard library will perform inequality comparison (i.e, '<')
160 : : /// in the way that the second elements (RRClass) are compared only when
161 : : /// the first elements are equivalent.
162 : : /// In practice, when we compare two pairs of RRType and RRClass, RRClass
163 : : /// would be the same (and, in particular, be class IN) in the majority of
164 : : /// cases. So this comparison ordering should be more efficient in common
165 : : /// cases.
166 : : typedef pair<RRType, RRClass> RRTypeClass;
167 : : typedef map<RRTypeClass, RdataFactoryPtr> RdataFactoryMap;
168 : : typedef map<RRType, RdataFactoryPtr> GenericRdataFactoryMap;
169 : :
170 : : template <typename T>
171 : 1377 : class RdataFactory : public AbstractRdataFactory {
172 : : public:
173 : 19518 : virtual RdataPtr create(const string& rdata_str) const
174 : : {
175 [ + + ][ + - ]: 19518 : return (RdataPtr(new T(rdata_str)));
[ + + ][ + + ]
[ + - ][ + - ]
[ # # ][ + - ]
[ + + ][ # # ]
[ # # ][ + - ]
[ # # ][ # # ]
[ + - ][ # # ]
[ + - ][ # # ]
[ + + ][ + - ]
[ + + ][ # # ]
[ + - ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
176 : : }
177 : :
178 : 1121 : virtual RdataPtr create(InputBuffer& buffer, size_t rdata_len) const
179 : : {
180 [ + + ][ + + ]: 1121 : return (RdataPtr(new T(buffer, rdata_len)));
[ + + ][ + + ]
[ + + ][ # # ]
[ + + ][ + - ]
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ # # ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + + ][ + - ]
[ # # ][ # # ]
[ + + ]
181 : : }
182 : :
183 : 10341 : virtual RdataPtr create(const Rdata& source) const
184 : : {
185 [ + + ][ + - ]: 10341 : return (RdataPtr(new T(dynamic_cast<const T&>(source))));
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ][ + - ]
[ # # ][ # # ]
[ + - ][ + - ]
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
186 : : }
187 : : };
188 : :
189 : : ///
190 : : /// \brief The \c RRParamRegistryImpl class is the actual implementation of
191 : : /// \c RRParamRegistry.
192 : : ///
193 : : /// The implementation is hidden from applications. We can refer to specific
194 : : /// members of this class only within the implementation source file.
195 : : ///
196 : 27 : struct RRParamRegistryImpl {
197 : : /// Mappings from RR type codes to textual representations.
198 : : StrRRTypeMap str2typemap;
199 : : /// Mappings from textual representations of RR types to integer codes.
200 : : CodeRRTypeMap code2typemap;
201 : : /// Mappings from RR class codes to textual representations.
202 : : StrRRClassMap str2classmap;
203 : : /// Mappings from textual representations of RR classes to integer codes.
204 : : CodeRRClassMap code2classmap;
205 : : RdataFactoryMap rdata_factories;
206 : : GenericRdataFactoryMap genericrdata_factories;
207 : : };
208 : :
209 : 27 : RRParamRegistry::RRParamRegistry() {
210 : 27 : impl_ = new RRParamRegistryImpl;
211 : :
212 : : // set up parameters for well-known RRs
213 : : try {
214 : : // BEGIN_WELL_KNOWN_PARAMS
215 [ + - ][ + - ]: 54 : add("A", 1, "IN", 1, RdataFactoryPtr(new RdataFactory<in::A>()));
[ + - ][ + - ]
216 [ + - ][ + - ]: 27 : add("NS", 2, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NS>()));
[ + - ][ + - ]
[ + - ]
217 [ + - ][ + - ]: 27 : add("CNAME", 5, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::CNAME>()));
[ + - ][ + - ]
[ + - ]
218 [ + - ][ + - ]: 27 : add("SOA", 6, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SOA>()));
[ + - ][ + - ]
[ + - ]
219 [ + - ][ + - ]: 27 : add("PTR", 12, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::PTR>()));
[ + - ][ + - ]
[ + - ]
220 [ + - ][ + - ]: 27 : add("HINFO", 13, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::HINFO>()));
[ + - ][ + - ]
[ + - ]
221 [ + - ][ + - ]: 27 : add("MINFO", 14, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::MINFO>()));
[ + - ][ + - ]
[ + - ]
222 [ + - ][ + - ]: 27 : add("MX", 15, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::MX>()));
[ + - ][ + - ]
[ + - ]
223 [ + - ][ + - ]: 27 : add("TXT", 16, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::TXT>()));
[ + - ][ + - ]
[ + - ]
224 [ + - ][ + - ]: 27 : add("RP", 17, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::RP>()));
[ + - ][ + - ]
[ + - ]
225 [ + - ][ + - ]: 27 : add("AFSDB", 18, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::AFSDB>()));
[ + - ][ + - ]
[ + - ]
226 [ + - ][ + - ]: 54 : add("AAAA", 28, "IN", 1, RdataFactoryPtr(new RdataFactory<in::AAAA>()));
[ + - ][ + - ]
227 [ + - ][ + - ]: 54 : add("SRV", 33, "IN", 1, RdataFactoryPtr(new RdataFactory<in::SRV>()));
[ + - ][ + - ]
228 [ + - ][ + - ]: 27 : add("NAPTR", 35, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NAPTR>()));
[ + - ][ + - ]
[ + - ]
229 [ + - ][ + - ]: 27 : add("DNAME", 39, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DNAME>()));
[ + - ][ + - ]
[ + - ]
230 [ + - ][ + - ]: 27 : add("OPT", 41, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::OPT>()));
[ + - ][ + - ]
[ + - ]
231 [ + - ][ + - ]: 27 : add("DS", 43, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DS>()));
[ + - ][ + - ]
[ + - ]
232 [ + - ][ + - ]: 27 : add("SSHFP", 44, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SSHFP>()));
[ + - ][ + - ]
[ + - ]
233 [ + - ][ + - ]: 27 : add("RRSIG", 46, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::RRSIG>()));
[ + - ][ + - ]
[ + - ]
234 [ + - ][ + - ]: 27 : add("NSEC", 47, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC>()));
[ + - ][ + - ]
[ + - ]
235 [ + - ][ + - ]: 27 : add("DNSKEY", 48, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DNSKEY>()));
[ + - ][ + - ]
[ + - ]
236 [ + - ][ + - ]: 54 : add("DHCID", 49, "IN", 1, RdataFactoryPtr(new RdataFactory<in::DHCID>()));
[ + - ][ + - ]
237 [ + - ][ + - ]: 27 : add("NSEC3", 50, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC3>()));
[ + - ][ + - ]
[ + - ]
238 [ + - ][ + - ]: 27 : add("NSEC3PARAM", 51, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::NSEC3PARAM>()));
[ + - ][ + - ]
[ + - ]
239 [ + - ][ + - ]: 27 : add("SPF", 99, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::SPF>()));
[ + - ][ + - ]
[ + - ]
240 [ + - ][ + - ]: 27 : add("DLV", 32769, "IN", 1, RdataFactoryPtr(new RdataFactory<generic::DLV>()));
[ + - ][ + - ]
[ + - ]
241 [ + - ][ + - ]: 54 : add("A", 1, "CH", 3, RdataFactoryPtr(new RdataFactory<ch::A>()));
[ + - ][ + - ]
242 [ + - ][ + - ]: 54 : add("A", 1, "HS", 4, RdataFactoryPtr(new RdataFactory<hs::A>()));
[ + - ][ + - ]
243 [ + - ][ + - ]: 54 : add("TSIG", 250, "ANY", 255, RdataFactoryPtr(new RdataFactory<any::TSIG>()));
[ + - ][ + - ]
244 [ + - ][ + - ]: 27 : add("NS", 2, RdataFactoryPtr(new RdataFactory<generic::NS>()));
[ + - ][ + - ]
245 [ + - ][ + - ]: 27 : add("CNAME", 5, RdataFactoryPtr(new RdataFactory<generic::CNAME>()));
[ + - ][ + - ]
246 [ + - ][ + - ]: 27 : add("SOA", 6, RdataFactoryPtr(new RdataFactory<generic::SOA>()));
[ + - ][ + - ]
247 [ + - ][ + - ]: 27 : add("PTR", 12, RdataFactoryPtr(new RdataFactory<generic::PTR>()));
[ + - ][ + - ]
248 [ + - ][ + - ]: 27 : add("HINFO", 13, RdataFactoryPtr(new RdataFactory<generic::HINFO>()));
[ + - ][ + - ]
249 [ + - ][ + - ]: 27 : add("MINFO", 14, RdataFactoryPtr(new RdataFactory<generic::MINFO>()));
[ + - ][ + - ]
250 [ + - ][ + - ]: 27 : add("MX", 15, RdataFactoryPtr(new RdataFactory<generic::MX>()));
[ + - ][ + - ]
251 [ + - ][ + - ]: 27 : add("TXT", 16, RdataFactoryPtr(new RdataFactory<generic::TXT>()));
[ + - ][ + - ]
252 [ + - ][ + - ]: 27 : add("RP", 17, RdataFactoryPtr(new RdataFactory<generic::RP>()));
[ + - ][ + - ]
253 [ + - ][ + - ]: 27 : add("AFSDB", 18, RdataFactoryPtr(new RdataFactory<generic::AFSDB>()));
[ + - ][ + - ]
254 [ + - ][ + - ]: 27 : add("NAPTR", 35, RdataFactoryPtr(new RdataFactory<generic::NAPTR>()));
[ + - ][ + - ]
255 [ + - ][ + - ]: 27 : add("DNAME", 39, RdataFactoryPtr(new RdataFactory<generic::DNAME>()));
[ + - ][ + - ]
256 [ + - ][ + - ]: 27 : add("OPT", 41, RdataFactoryPtr(new RdataFactory<generic::OPT>()));
[ + - ][ + - ]
257 [ + - ][ + - ]: 27 : add("DS", 43, RdataFactoryPtr(new RdataFactory<generic::DS>()));
[ + - ][ + - ]
258 [ + - ][ + - ]: 27 : add("SSHFP", 44, RdataFactoryPtr(new RdataFactory<generic::SSHFP>()));
[ + - ][ + - ]
259 [ + - ][ + - ]: 27 : add("RRSIG", 46, RdataFactoryPtr(new RdataFactory<generic::RRSIG>()));
[ + - ][ + - ]
260 [ + - ][ + - ]: 27 : add("NSEC", 47, RdataFactoryPtr(new RdataFactory<generic::NSEC>()));
[ + - ][ + - ]
261 [ + - ][ + - ]: 27 : add("DNSKEY", 48, RdataFactoryPtr(new RdataFactory<generic::DNSKEY>()));
[ + - ][ + - ]
262 [ + - ][ + - ]: 27 : add("NSEC3", 50, RdataFactoryPtr(new RdataFactory<generic::NSEC3>()));
[ + - ][ + - ]
263 [ + - ][ + - ]: 27 : add("NSEC3PARAM", 51, RdataFactoryPtr(new RdataFactory<generic::NSEC3PARAM>()));
[ + - ][ + - ]
264 [ + - ][ + - ]: 27 : add("SPF", 99, RdataFactoryPtr(new RdataFactory<generic::SPF>()));
[ + - ][ + - ]
265 [ + - ][ + - ]: 27 : add("DLV", 32769, RdataFactoryPtr(new RdataFactory<generic::DLV>()));
[ + - ][ + - ]
266 : : // END_WELL_KNOWN_PARAMS
267 : 0 : } catch (...) {
268 [ # # ][ # # ]: 0 : delete impl_;
269 : 0 : throw;
270 : : }
271 : 27 : }
272 : :
273 : 27 : RRParamRegistry::~RRParamRegistry() {
274 [ + - ]: 27 : delete impl_;
275 : 27 : }
276 : :
277 : : RRParamRegistry&
278 : 109428 : RRParamRegistry::getRegistry() {
279 [ + + ][ + - ]: 109428 : static RRParamRegistry registry;
[ + - ]
280 : :
281 : 109428 : return (registry);
282 : : }
283 : :
284 : : void
285 : 595 : RRParamRegistry::add(const string& typecode_string, uint16_t typecode,
286 : : RdataFactoryPtr rdata_factory)
287 : : {
288 : 595 : bool type_added = false;
289 : : try {
290 [ + - ]: 595 : type_added = addType(typecode_string, typecode);
291 : : impl_->genericrdata_factories.insert(pair<RRType, RdataFactoryPtr>(
292 : : RRType(typecode),
293 : 1190 : rdata_factory));
294 : 0 : } catch (...) {
295 [ # # ]: 0 : if (type_added) {
296 [ # # ]: 0 : removeType(typecode);
297 : : }
298 : 0 : throw;
299 : : }
300 : 595 : }
301 : :
302 : : void
303 : 784 : RRParamRegistry::add(const string& typecode_string, uint16_t typecode,
304 : : const string& classcode_string, uint16_t classcode,
305 : : RdataFactoryPtr rdata_factory)
306 : : {
307 : : // Rollback logic on failure is complicated. If adding the new type or
308 : : // class fails, we should revert to the original state, cleaning up
309 : : // intermediate state. But we need to make sure that we don't remove
310 : : // existing data. addType()/addClass() will simply ignore an attempt to
311 : : // add the same data, so the cleanup should be performed only when we add
312 : : // something new but we fail in other part of the process.
313 : 784 : bool type_added = false;
314 : 784 : bool class_added = false;
315 : :
316 : : try {
317 [ + - ]: 784 : type_added = addType(typecode_string, typecode);
318 [ + - ]: 784 : class_added = addClass(classcode_string, classcode);
319 : : impl_->rdata_factories.insert(pair<RRTypeClass, RdataFactoryPtr>(
320 : : RRTypeClass(RRType(typecode),
321 : : RRClass(classcode)),
322 : 1568 : rdata_factory));
323 : 0 : } catch (...) {
324 [ # # ]: 0 : if (type_added) {
325 [ # # ]: 0 : removeType(typecode);
326 : : }
327 [ # # ]: 0 : if (class_added) {
328 [ # # ]: 0 : removeClass(classcode);
329 : : }
330 : 0 : throw;
331 : : }
332 : 784 : }
333 : :
334 : : bool
335 : 5 : RRParamRegistry::removeRdataFactory(const RRType& rrtype,
336 : : const RRClass& rrclass)
337 : : {
338 : : RdataFactoryMap::iterator found =
339 : 10 : impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
340 [ + + ]: 5 : if (found != impl_->rdata_factories.end()) {
341 : 1 : impl_->rdata_factories.erase(found);
342 : 5 : return (true);
343 : : }
344 : :
345 : : return (false);
346 : : }
347 : :
348 : : bool
349 : 5 : RRParamRegistry::removeRdataFactory(const RRType& rrtype) {
350 : : GenericRdataFactoryMap::iterator found =
351 : 5 : impl_->genericrdata_factories.find(rrtype);
352 [ + + ]: 5 : if (found != impl_->genericrdata_factories.end()) {
353 : 1 : impl_->genericrdata_factories.erase(found);
354 : 5 : return (true);
355 : : }
356 : :
357 : : return (false);
358 : : }
359 : :
360 : : namespace {
361 : : ///
362 : : /// These are helper functions to implement case-insensitive string comparison.
363 : : /// This could be simplified using strncasecmp(), but unfortunately it's not
364 : : /// included in <cstring>. To be as much as portable within the C++ standard
365 : : /// we take the "in house" approach here.
366 : : ///
367 : 469 : bool CICharEqual(char c1, char c2) {
368 : 469 : return (tolower(static_cast<unsigned char>(c1)) ==
369 : 469 : tolower(static_cast<unsigned char>(c2)));
370 : : }
371 : :
372 : : bool
373 : 120 : caseStringEqual(const string& s1, const string& s2, size_t n) {
374 [ + - ][ - + ]: 120 : assert(s1.size() >= n && s2.size() >= n);
375 : :
376 : 120 : return (mismatch(s1.begin(), s1.begin() + n, s2.begin(), CICharEqual).first
377 : 120 : == s1.begin() + n);
378 : : }
379 : :
380 : : /// Code logic for RRTypes and RRClasses is mostly common except (C++) type and
381 : : /// member names. So we define type-independent templates to describe the
382 : : /// common logic and let concrete classes use it to avoid code duplicates.
383 : : /// The following summarize template parameters used in the set of template
384 : : /// functions:
385 : : /// PT: parameter type, either RRTypeParam or RRClassParam
386 : : /// MC: type of mapping class from code: either CodeRRTypeMap or CodeRRClassMap
387 : : /// MS: type of mapping class from string: either StrRRTypeMap or StrRRClassMap
388 : : /// ET: exception type for error handling: either InvalidRRType or
389 : : /// InvalidRRClass
390 : : template <typename PT, typename MC, typename MS, typename ET>
391 : : inline bool
392 : 2167 : addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
393 : : {
394 : : // Duplicate type check
395 : 2167 : typename MC::const_iterator found = codemap.find(code);
396 [ + + + + ]: 2167 : if (found != codemap.end()) {
397 [ + + ][ + + ]: 1326 : if (found->second->code_string_ != code_string) {
398 [ + - ][ + - ]: 4 : isc_throw(ET, "Duplicate RR parameter registration");
399 : : }
400 : : return (false);
401 : : }
402 : :
403 : : typedef boost::shared_ptr<PT> ParamPtr;
404 : : typedef pair<string, ParamPtr> StrParamPair;
405 : : typedef pair<uint16_t, ParamPtr> CodeParamPair;
406 : 841 : ParamPtr param = ParamPtr(new PT(code_string, code));
407 : : try {
408 [ + - ][ + - ]: 841 : stringmap.insert(StrParamPair(code_string, param));
409 : : codemap.insert(CodeParamPair(code, param));
410 : 0 : } catch (...) {
411 : : // Rollback to the previous state: not all of the erase operations will
412 : : // find the entry, but we don't care.
413 [ # # # # ]: 0 : stringmap.erase(code_string);
414 : : codemap.erase(code);
415 : 0 : throw;
416 : : }
417 : :
418 : 841 : return (true);
419 : : }
420 : :
421 : : template <typename MC, typename MS>
422 : : inline bool
423 : : removeParam(uint16_t code, MC& codemap, MS& stringmap) {
424 : 10 : typename MC::iterator found = codemap.find(code);
425 : :
426 [ + + + + ]: 10 : if (found != codemap.end()) {
427 : 4 : size_t erased = stringmap.erase(found->second->code_string_);
428 : : // We must have a corresponding entry of the str2 map exists
429 [ - + ][ - + ]: 4 : assert(erased == 1);
430 : :
431 : : codemap.erase(found);
432 : :
433 : : return (true);
434 : : }
435 : :
436 : : return (false);
437 : : }
438 : :
439 : : template <typename PT, typename MS, typename ET>
440 : : inline uint16_t
441 : 46974 : textToCode(const string& code_str, MS& stringmap) {
442 : : typename MS::const_iterator found;
443 : :
444 : 46974 : found = stringmap.find(code_str);
445 [ + + ][ + + ]: 46974 : if (found != stringmap.end()) {
446 : 46831 : return (found->second->code_);
447 : : }
448 : :
449 : 143 : size_t l = code_str.size();
450 [ + + ][ + + ]: 274 : if (l > PT::UNKNOWN_PREFIXLEN() &&
[ + + ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
451 : : l <= PT::UNKNOWN_MAXLEN() &&
452 : : caseStringEqual(code_str, PT::UNKNOWN_PREFIX(),
453 : : PT::UNKNOWN_PREFIXLEN())) {
454 : : unsigned int code;
455 : : istringstream iss(code_str.substr(PT::UNKNOWN_PREFIXLEN(),
456 [ + - ][ + - ]: 226 : l - PT::UNKNOWN_PREFIXLEN()));
457 : 113 : iss >> dec >> code;
458 [ + + ][ + + ]: 113 : if (iss.rdstate() == ios::eofbit && code <= PT::MAX_CODE) {
[ + + ][ + + ]
[ + + ][ + + ]
459 : 101 : return (code);
460 : : }
461 : : }
462 [ + - ][ + - ]: 47016 : isc_throw(ET, "Unrecognized RR parameter string");
463 : : }
464 : :
465 : : template <typename PT, typename MC>
466 : : inline string
467 : 31161 : codeToText(uint16_t code, MC& codemap) {
468 : : typename MC::const_iterator found;
469 : :
470 : 31161 : found = codemap.find(code);
471 [ + + + + ]: 31161 : if (found != codemap.end()) {
472 : 30413 : return (found->second->code_string_);
473 : : }
474 : :
475 : 31909 : ostringstream ss;
476 : 748 : ss << code;
477 [ + - ][ + - ]: 748 : return (PT::UNKNOWN_PREFIX() + ss.str());
[ + - ][ + - ]
478 : : }
479 : : }
480 : :
481 : : bool
482 : 1381 : RRParamRegistry::addType(const string& type_string, uint16_t code) {
483 : : return (addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap, RRTypeExists>
484 : 1381 : (type_string, code, impl_->code2typemap, impl_->str2typemap));
485 : : }
486 : :
487 : : bool
488 : 5 : RRParamRegistry::removeType(uint16_t code) {
489 : : return (removeParam<CodeRRTypeMap, StrRRTypeMap>(code, impl_->code2typemap,
490 : 5 : impl_->str2typemap));
491 : : }
492 : :
493 : : uint16_t
494 : 35767 : RRParamRegistry::textToTypeCode(const string& type_string) const {
495 : : return (textToCode<RRTypeParam, StrRRTypeMap,
496 : 35767 : InvalidRRType>(type_string, impl_->str2typemap));
497 : : }
498 : :
499 : : string
500 : 21030 : RRParamRegistry::codeToTypeText(uint16_t code) const {
501 : 21030 : return (codeToText<RRTypeParam, CodeRRTypeMap>(code, impl_->code2typemap));
502 : : }
503 : :
504 : : bool
505 : 786 : RRParamRegistry::addClass(const string& class_string, uint16_t code) {
506 : : return (addParam<RRClassParam, CodeRRClassMap, StrRRClassMap, RRClassExists>
507 : 786 : (class_string, code, impl_->code2classmap, impl_->str2classmap));
508 : : }
509 : :
510 : : bool
511 : 5 : RRParamRegistry::removeClass(uint16_t code) {
512 : : return (removeParam<CodeRRClassMap, StrRRClassMap>(code,
513 : : impl_->code2classmap,
514 : 5 : impl_->str2classmap));
515 : : }
516 : :
517 : : uint16_t
518 : 11207 : RRParamRegistry::textToClassCode(const string& class_string) const {
519 : : return (textToCode<RRClassParam, StrRRClassMap,
520 : 11207 : InvalidRRClass>(class_string, impl_->str2classmap));
521 : : }
522 : :
523 : : string
524 : 10131 : RRParamRegistry::codeToClassText(uint16_t code) const {
525 : : return (codeToText<RRClassParam, CodeRRClassMap>(code,
526 : 10131 : impl_->code2classmap));
527 : : }
528 : :
529 : : RdataPtr
530 : 19767 : RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
531 : : const string& rdata_string)
532 : : {
533 : : // If the text indicates that it's rdata of an "unknown" type (beginning
534 : : // with '\# n'), parse it that way. (TBD)
535 : :
536 : : RdataFactoryMap::const_iterator found;
537 : 39534 : found = impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
538 [ + + ]: 19767 : if (found != impl_->rdata_factories.end()) {
539 : 19400 : return (found->second->create(rdata_string));
540 : : }
541 : :
542 : : GenericRdataFactoryMap::const_iterator genfound =
543 : 367 : impl_->genericrdata_factories.find(rrtype);
544 [ + + ]: 367 : if (genfound != impl_->genericrdata_factories.end()) {
545 : 120 : return (genfound->second->create(rdata_string));
546 : : }
547 : :
548 [ + + ]: 19720 : return (RdataPtr(new generic::Generic(rdata_string)));
549 : : }
550 : :
551 : : RdataPtr
552 : 1135 : RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
553 : : InputBuffer& buffer, size_t rdata_len)
554 : : {
555 : : RdataFactoryMap::const_iterator found =
556 : 2270 : impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
557 [ + + ]: 1135 : if (found != impl_->rdata_factories.end()) {
558 : 1065 : return (found->second->create(buffer, rdata_len));
559 : : }
560 : :
561 : : GenericRdataFactoryMap::const_iterator genfound =
562 : 70 : impl_->genericrdata_factories.find(rrtype);
563 [ + + ]: 70 : if (genfound != impl_->genericrdata_factories.end()) {
564 : 56 : return (genfound->second->create(buffer, rdata_len));
565 : : }
566 : :
567 [ + + ]: 1036 : return (RdataPtr(new generic::Generic(buffer, rdata_len)));
568 : : }
569 : :
570 : : RdataPtr
571 : 10365 : RRParamRegistry::createRdata(const RRType& rrtype, const RRClass& rrclass,
572 : : const Rdata& source)
573 : : {
574 : : RdataFactoryMap::const_iterator found =
575 : 20730 : impl_->rdata_factories.find(RRTypeClass(rrtype, rrclass));
576 [ + + ]: 10365 : if (found != impl_->rdata_factories.end()) {
577 : 6081 : return (found->second->create(source));
578 : : }
579 : :
580 : : GenericRdataFactoryMap::const_iterator genfound =
581 : 4284 : impl_->genericrdata_factories.find(rrtype);
582 [ + + ]: 4284 : if (genfound != impl_->genericrdata_factories.end()) {
583 : 4260 : return (genfound->second->create(source));
584 : : }
585 : :
586 : : return (RdataPtr(new rdata::generic::Generic(
587 [ + - ][ + - ]: 10363 : dynamic_cast<const generic::Generic&>(source))));
588 : : }
589 : : }
590 : 98468 : }
|