Branch data Line data Source code
1 : : // Copyright (C) 2012 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 : : #include <cc/data.h>
16 : :
17 : : #include <dns/rrclass.h>
18 : :
19 : : #include <datasrc/client.h>
20 : : #include <datasrc/memory_datasrc.h>
21 : :
22 : : #include <boost/foreach.hpp>
23 : :
24 : : #include <string>
25 : :
26 : : using namespace isc::dns;
27 : : using namespace isc::data;
28 : :
29 : : namespace isc {
30 : : namespace datasrc {
31 : :
32 : : namespace {
33 : : // convencience function to add an error message to a list of those
34 : : // (TODO: move functions like these to some util lib?)
35 : : void
36 : 31 : addError(ElementPtr errors, const std::string& error) {
37 [ + - ][ - + ]: 62 : if (errors != ElementPtr() && errors->getType() == Element::list) {
[ + - ]
38 [ + - ]: 62 : errors->add(Element::create(error));
39 : : }
40 : 31 : }
41 : :
42 : : /// Check if the given element exists in the map, and if it is a string
43 : : bool
44 : 30 : checkConfigElementString(ConstElementPtr config, const std::string& name,
45 : : ElementPtr errors)
46 : : {
47 [ + + ]: 30 : if (!config->contains(name)) {
48 : : addError(errors,
49 : : "Config for memory backend does not contain a '"
50 : 10 : +name+
51 [ + - ][ + - ]: 30 : "' value");
52 : 10 : return false;
53 [ + - ]: 58 : } else if (!config->get(name) ||
[ + + + + ]
[ + + ][ # # ]
54 [ + - ][ + + ]: 38 : config->get(name)->getType() != Element::string) {
55 : 4 : addError(errors, "value of " + name +
56 [ + - ][ + - ]: 12 : " in memory backend config is not a string");
57 : 30 : return false;
58 : : } else {
59 : : return true;
60 : : }
61 : : }
62 : :
63 : : bool
64 : 0 : checkZoneConfig(ConstElementPtr config, ElementPtr errors) {
65 : 0 : bool result = true;
66 [ # # ][ # # ]: 0 : if (!config || config->getType() != Element::map) {
[ # # ]
67 [ # # ]: 0 : addError(errors, "Elements in memory backend's zone list must be maps");
68 : : result = false;
69 : : } else {
70 [ # # ][ # # ]: 0 : if (!checkConfigElementString(config, "origin", errors)) {
[ # # ]
71 : 0 : result = false;
72 : : }
73 [ # # ][ # # ]: 0 : if (!checkConfigElementString(config, "file", errors)) {
[ # # ]
74 : 0 : result = false;
75 : : }
76 : : // we could add some existence/readabilty/parsability checks here
77 : : // if we want
78 : : }
79 : 0 : return result;
80 : : }
81 : :
82 : : bool
83 : 17 : checkConfig(ConstElementPtr config, ElementPtr errors) {
84 : : /* Specific configuration is under discussion, right now this accepts
85 : : * the 'old' configuration, see [TODO]
86 : : * So for memory datasource, we get a structure like this:
87 : : * { "type": string ("memory"),
88 : : * "class": string ("IN"/"CH"/etc),
89 : : * "zones": list
90 : : * }
91 : : * Zones list is a list of maps:
92 : : * { "origin": string,
93 : : * "file": string
94 : : * }
95 : : *
96 : : * At this moment we cannot be completely sure of the contents of the
97 : : * structure, so we have to do some more extensive tests than should
98 : : * strictly be necessary (e.g. existence and type of elements)
99 : : */
100 : 17 : bool result = true;
101 : :
102 [ + + ][ + + ]: 17 : if (!config || config->getType() != Element::map) {
[ + + ]
103 [ + - ]: 6 : addError(errors, "Base config for memory backend must be a map");
104 : : result = false;
105 : : } else {
106 [ + - ][ + - ]: 60 : if (!checkConfigElementString(config, "type", errors)) {
[ + + ]
107 : : result = false;
108 : : } else {
109 [ + - ][ + - ]: 30 : if (config->get("type")->stringValue() != "memory") {
[ + + ]
110 : : addError(errors,
111 [ + - ]: 3 : "Config for memory backend is not of type \"memory\"");
112 : : result = false;
113 : : }
114 : : }
115 [ + - ][ + - ]: 60 : if (!checkConfigElementString(config, "class", errors)) {
[ + + ]
116 : : result = false;
117 : : } else {
118 : : try {
119 [ + - ][ + - ]: 12 : RRClass rrc(config->get("class")->stringValue());
[ + - ][ + + ]
120 [ - + ]: 2 : } catch (const isc::Exception& rrce) {
121 : : addError(errors,
122 : : "Error parsing class config for memory backend: " +
123 [ - + ][ - + ]: 3 : std::string(rrce.what()));
[ - + ]
124 : 1 : result = false;
125 : : }
126 : : }
127 [ + - ][ + + ]: 15 : if (!config->contains("zones")) {
128 [ + - ]: 33 : addError(errors, "No 'zones' element in memory backend config");
129 : : result = false;
130 [ + - ][ + - ]: 11 : } else if (!config->get("zones") ||
[ + + + + ]
[ + + ][ # # ]
[ # # ]
131 [ + - ][ + - ]: 10 : config->get("zones")->getType() != Element::list) {
[ + + ][ + + ]
[ # # ]
132 [ + - ]: 6 : addError(errors, "'zones' element in memory backend config is not a list");
133 : : result = false;
134 : : } else {
135 [ + - ][ + - ]: 4 : BOOST_FOREACH(ConstElementPtr zone_config,
[ # # # # ]
[ + - ][ + - ]
[ - + ]
136 : : config->get("zones")->listValue()) {
137 [ # # ][ # # ]: 0 : if (!checkZoneConfig(zone_config, errors)) {
138 : 0 : result = false;
139 : : }
140 : : }
141 : : }
142 : : }
143 : :
144 : 17 : return (result);
145 : : }
146 : :
147 : : } // end unnamed namespace
148 : :
149 : : DataSourceClient *
150 : 17 : createInstance(isc::data::ConstElementPtr config, std::string& error) {
151 : 17 : ElementPtr errors(Element::createList());
152 [ + - ][ + + ]: 34 : if (!checkConfig(config, errors)) {
153 [ + - ][ + - ]: 30 : error = "Configuration error: " + errors->str();
154 : : return (NULL);
155 : : }
156 : : try {
157 [ + - ][ + - ]: 2 : return (new isc::datasrc::InMemoryClient());
158 : 0 : } catch (const std::exception& exc) {
159 [ # # ][ # # ]: 0 : error = std::string("Error creating memory datasource: ") + exc.what();
160 : : return (NULL);
161 [ # # ][ # # ]: 0 : } catch (...) {
162 : : error = std::string("Error creating memory datasource, "
163 [ # # ]: 0 : "unknown exception");
164 : : return (NULL);
165 : : }
166 : : }
167 : :
168 : 2 : void destroyInstance(DataSourceClient* instance) {
169 [ + - ]: 2 : delete instance;
170 : 2 : }
171 : :
172 : : } // end of namespace datasrc
173 : 2 : } // end of namespace isc
|