Kea 1.5.0
d2_cfg_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <d2/d2_log.h>
10#include <d2/d2_cfg_mgr.h>
11#include <d2/d2_simple_parser.h>
13#include <util/encode/hex.h>
14
15#include <boost/foreach.hpp>
16
17using namespace isc::asiolink;
18using namespace isc::config;
19using namespace isc::data;
20using namespace isc::process;
21
22namespace isc {
23namespace d2 {
24
25namespace {
26
27typedef std::vector<uint8_t> ByteAddress;
28
29} // end of unnamed namespace
30
31// *********************** D2CfgContext *************************
32
34 : d2_params_(new D2Params()),
35 forward_mgr_(new DdnsDomainListMgr("forward-ddns")),
36 reverse_mgr_(new DdnsDomainListMgr("reverse-ddns")),
37 keys_(new TSIGKeyInfoMap()) {
38}
39
41 d2_params_ = rhs.d2_params_;
42 if (rhs.forward_mgr_) {
43 forward_mgr_.reset(new DdnsDomainListMgr(rhs.forward_mgr_->getName()));
44 forward_mgr_->setDomains(rhs.forward_mgr_->getDomains());
45 }
46
47 if (rhs.reverse_mgr_) {
48 reverse_mgr_.reset(new DdnsDomainListMgr(rhs.reverse_mgr_->getName()));
49 reverse_mgr_->setDomains(rhs.reverse_mgr_->getDomains());
50 }
51
52 keys_ = rhs.keys_;
53}
54
56}
57
61 // Set user-context
63 // Set ip-address
64 const IOAddress& ip_address = d2_params_->getIpAddress();
65 d2->set("ip-address", Element::create(ip_address.toText()));
66 // Set port
67 size_t port = d2_params_->getPort();
68 d2->set("port", Element::create(static_cast<int64_t>(port)));
69 // Set dns-server-timeout
70 size_t dns_server_timeout = d2_params_->getDnsServerTimeout();
71 d2->set("dns-server-timeout",
72 Element::create(static_cast<int64_t>(dns_server_timeout)));
73 // Set ncr-protocol
74 const dhcp_ddns::NameChangeProtocol& ncr_protocol =
75 d2_params_->getNcrProtocol();
76 d2->set("ncr-protocol",
78 // Set ncr-format
79 const dhcp_ddns::NameChangeFormat& ncr_format = d2_params_->getNcrFormat();
80 d2->set("ncr-format",
82 // Set forward-ddns
83 ElementPtr forward_ddns = Element::createMap();
84 forward_ddns->set("ddns-domains", forward_mgr_->toElement());
85 d2->set("forward-ddns", forward_ddns);
86 // Set reverse-ddns
87 ElementPtr reverse_ddns = Element::createMap();
88 reverse_ddns->set("ddns-domains", reverse_mgr_->toElement());
89 d2->set("reverse-ddns", reverse_ddns);
90 // Set tsig-keys
91 ElementPtr tsig_keys = Element::createList();
92 for (TSIGKeyInfoMap::const_iterator key = keys_->begin();
93 key != keys_->end(); ++key) {
94 tsig_keys->add(key->second->toElement());
95 }
96 d2->set("tsig-keys", tsig_keys);
97 // Set DhcpDdns
99 result->set("DhcpDdns", d2);
100
101 return (result);
102}
103
104// *********************** D2CfgMgr *************************
105
106const char* D2CfgMgr::IPV4_REV_ZONE_SUFFIX = "in-addr.arpa.";
107
108const char* D2CfgMgr::IPV6_REV_ZONE_SUFFIX = "ip6.arpa.";
109
111}
112
114}
115
118 return (ConfigPtr(new D2CfgContext()));
119}
120
121bool
123 // Forward updates are not enabled if no forward servers are defined.
124 return (getD2CfgContext()->getForwardMgr()->size() > 0);
125}
126
127bool
129 // Reverse updates are not enabled if no reverse servers are defined.
130 return (getD2CfgContext()->getReverseMgr()->size() > 0);
131}
132
133bool
134D2CfgMgr::matchForward(const std::string& fqdn, DdnsDomainPtr& domain) {
135 if (fqdn.empty()) {
136 // This is a programmatic error and should not happen.
137 isc_throw(D2CfgError, "matchForward passed an empty fqdn");
138 }
139
140 // Fetch the forward manager from the D2 context.
141 DdnsDomainListMgrPtr mgr = getD2CfgContext()->getForwardMgr();
142
143 // Call the manager's match method and return the result.
144 return (mgr->matchDomain(fqdn, domain));
145}
146
147bool
148D2CfgMgr::matchReverse(const std::string& ip_address, DdnsDomainPtr& domain) {
149 // Note, reverseIpAddress will throw if the ip_address is invalid.
150 std::string reverse_address = reverseIpAddress(ip_address);
151
152 // Fetch the reverse manager from the D2 context.
153 DdnsDomainListMgrPtr mgr = getD2CfgContext()->getReverseMgr();
154
155 return (mgr->matchDomain(reverse_address, domain));
156}
157
158std::string
159D2CfgMgr::reverseIpAddress(const std::string& address) {
160 try {
161 // Convert string address into an IOAddress and invoke the
162 // appropriate reverse method.
163 isc::asiolink::IOAddress ioaddr(address);
164 if (ioaddr.isV4()) {
165 return (reverseV4Address(ioaddr));
166 }
167
168 return (reverseV6Address(ioaddr));
169
170 } catch (const isc::Exception& ex) {
171 isc_throw(D2CfgError, "D2CfgMgr cannot reverse address: "
172 << address << " : " << ex.what());
173 }
174}
175
176std::string
178 if (!ioaddr.isV4()) {
179 isc_throw(D2CfgError, "D2CfgMgr address is not IPv4 address :"
180 << ioaddr);
181 }
182
183 // Get the address in byte vector form.
184 const ByteAddress bytes = ioaddr.toBytes();
185
186 // Walk backwards through vector outputting each octet and a dot.
187 std::ostringstream stream;
188
189 // We have to set the following variable to get
190 // const_reverse_iterator type of rend(), otherwise Solaris GCC
191 // complains on operator!= by trying to use the non-const variant.
192 const ByteAddress::const_reverse_iterator end = bytes.rend();
193
194 for (ByteAddress::const_reverse_iterator rit = bytes.rbegin();
195 rit != end;
196 ++rit)
197 {
198 stream << static_cast<unsigned int>(*rit) << ".";
199 }
200
201 // Tack on the suffix and we're done.
202 stream << IPV4_REV_ZONE_SUFFIX;
203 return(stream.str());
204}
205
206std::string
208 if (!ioaddr.isV6()) {
209 isc_throw(D2CfgError, "D2Cfg address is not IPv6 address: " << ioaddr);
210 }
211
212 // Turn the address into a string of digits.
213 const ByteAddress bytes = ioaddr.toBytes();
214 const std::string digits = isc::util::encode::encodeHex(bytes);
215
216 // Walk backwards through string outputting each digits and a dot.
217 std::ostringstream stream;
218
219 // We have to set the following variable to get
220 // const_reverse_iterator type of rend(), otherwise Solaris GCC
221 // complains on operator!= by trying to use the non-const variant.
222 const std::string::const_reverse_iterator end = digits.rend();
223
224 for (std::string::const_reverse_iterator rit = digits.rbegin();
225 rit != end;
226 ++rit)
227 {
228 stream << static_cast<char>(*rit) << ".";
229 }
230
231 // Tack on the suffix and we're done.
232 stream << IPV6_REV_ZONE_SUFFIX;
233 return(stream.str());
234}
235
236const D2ParamsPtr&
238 return (getD2CfgContext()->getD2Params());
239}
240
241std::string
243 return (getD2Params()->getConfigSummary());
244}
245
246void
248 D2SimpleParser::setAllDefaults(mutable_config);
249}
250
252D2CfgMgr::parse(isc::data::ConstElementPtr config_set, bool check_only) {
253 // Do a sanity check first.
254 if (!config_set) {
255 isc_throw(D2CfgError, "Mandatory config parameter not provided");
256 }
257
259
260 // Set the defaults
261 ElementPtr cfg = boost::const_pointer_cast<Element>(config_set);
263
264 // And parse the configuration.
265 ConstElementPtr answer;
266 std::string excuse;
267 try {
268 // Do the actual parsing
269 D2SimpleParser parser;
270 parser.parse(ctx, cfg, check_only);
271 } catch (const isc::Exception& ex) {
272 excuse = ex.what();
273 answer = createAnswer(CONTROL_RESULT_ERROR, excuse);
274 } catch (...) {
275 excuse = "undefined configuration parsing error";
276 answer = createAnswer(CONTROL_RESULT_ERROR, excuse);
277 }
278
279 // At this stage the answer was created only in case of exception.
280 if (answer) {
281 if (check_only) {
282 LOG_ERROR(d2_logger, DHCP_DDNS_CONFIG_CHECK_FAIL).arg(excuse);
283 } else {
284 LOG_ERROR(d2_logger, DHCP_DDNS_CONFIG_FAIL).arg(excuse);
285 }
286 return (answer);
287 }
288
289 if (check_only) {
291 "Configuration check successful");
292 } else {
294 "Configuration applied successfully.");
295 }
296
297 return (answer);
298}
299
300
301}; // end of isc::dhcp namespace
302}; // end of isc namespace
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
DHCP-DDNS Configuration Context.
Definition: d2_cfg_mgr.h:33
virtual ~D2CfgContext()
Destructor.
Definition: d2_cfg_mgr.cc:55
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: d2_cfg_mgr.cc:59
D2CfgContext()
Constructor.
Definition: d2_cfg_mgr.cc:33
Exception thrown when the error during configuration handling occurs.
Definition: d2_config.h:130
virtual ~D2CfgMgr()
Destructor.
Definition: d2_cfg_mgr.cc:113
virtual void setCfgDefaults(isc::data::ElementPtr mutable_config)
Adds default values to the given config.
Definition: d2_cfg_mgr.cc:247
bool matchForward(const std::string &fqdn, DdnsDomainPtr &domain)
Matches a given FQDN to a forward domain.
Definition: d2_cfg_mgr.cc:134
static std::string reverseIpAddress(const std::string &address)
Generate a reverse order string for the given IP address.
Definition: d2_cfg_mgr.cc:159
D2CfgContextPtr getD2CfgContext()
Convenience method that returns the D2 configuration context.
Definition: d2_cfg_mgr.h:149
bool reverseUpdatesEnabled()
Returns whether or not reverse updates are enabled.
Definition: d2_cfg_mgr.cc:128
virtual process::ConfigPtr createNewContext()
Creates an new, blank D2CfgContext context.
Definition: d2_cfg_mgr.cc:117
D2CfgMgr()
Constructor.
Definition: d2_cfg_mgr.cc:110
static const char * IPV6_REV_ZONE_SUFFIX
Reverse zone suffix added to IPv6 addresses for reverse lookups.
Definition: d2_cfg_mgr.h:138
virtual std::string getConfigSummary(const uint32_t selection)
Returns configuration summary in the textual format.
Definition: d2_cfg_mgr.cc:242
static std::string reverseV4Address(const isc::asiolink::IOAddress &ioaddr)
Generate a reverse order string for the given IP address.
Definition: d2_cfg_mgr.cc:177
bool forwardUpdatesEnabled()
Returns whether or not forward updates are enabled.
Definition: d2_cfg_mgr.cc:122
bool matchReverse(const std::string &ip_address, DdnsDomainPtr &domain)
Matches a given IP address to a reverse domain.
Definition: d2_cfg_mgr.cc:148
static std::string reverseV6Address(const isc::asiolink::IOAddress &ioaddr)
Generate a reverse order string for the given IP address.
Definition: d2_cfg_mgr.cc:207
const D2ParamsPtr & getD2Params()
Convenience method fetches the D2Params from context.
Definition: d2_cfg_mgr.cc:237
virtual isc::data::ConstElementPtr parse(isc::data::ConstElementPtr config, bool check_only)
Parses configuration of the D2.
Definition: d2_cfg_mgr.cc:252
static const char * IPV4_REV_ZONE_SUFFIX
Reverse zone suffix added to IPv4 addresses for reverse lookups.
Definition: d2_cfg_mgr.h:134
Acts as a storage vault for D2 global scalar parameters.
Definition: d2_config.h:137
void parse(const D2CfgContextPtr &ctx, const isc::data::ConstElementPtr &config, bool check_only)
Parses the whole D2 configuration.
static size_t setAllDefaults(data::ElementPtr global)
Sets all defaults for D2 configuration.
Provides storage for and management of a list of DNS domains.
Definition: d2_config.h:608
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:223
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition: data.cc:268
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:263
Base class for all configurations.
Definition: config_base.h:31
Configuration Manager.
Definition: d_cfg_mgr.h:106
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< DdnsDomainListMgr > DdnsDomainListMgrPtr
Defines a pointer for DdnsDomain instances.
Definition: d2_cfg_mgr.h:120
boost::shared_ptr< DdnsDomain > DdnsDomainPtr
Defines a pointer for DdnsDomain instances.
Definition: d2_config.h:586
std::map< std::string, TSIGKeyInfoPtr > TSIGKeyInfoMap
Defines a map of TSIGKeyInfos, keyed by the name.
Definition: d2_config.h:401
boost::shared_ptr< D2CfgContext > D2CfgContextPtr
Pointer to a configuration context.
Definition: d2_cfg_mgr.h:24
isc::log::Logger d2_logger("dhcpddns")
Defines the logger used within D2.
Definition: d2_log.h:18
boost::shared_ptr< D2Params > D2ParamsPtr
Defines a pointer for D2Params instances.
Definition: d2_config.h:251
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
NameChangeFormat
Defines the list of data wire formats supported.
Definition: ncr_msg.h:60
NameChangeProtocol
Defines the list of socket protocols supported.
Definition: ncr_io.h:66
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition: ncr_io.cc:30
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition: ncr_msg.cc:36
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the SrvConfig.
Definition: config_base.h:119
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:461
Defines the logger used by the top-level component of kea-dhcp-ddns.
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition: user_context.cc:15