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>
12 #include <cc/command_interpreter.h>
13 #include <util/encode/hex.h>
14 
15 #include <boost/foreach.hpp>
16 
17 using namespace isc::asiolink;
18 using namespace isc::config;
19 using namespace isc::data;
20 using namespace isc::process;
21 
22 namespace isc {
23 namespace d2 {
24 
25 namespace {
26 
27 typedef std::vector<uint8_t> ByteAddress;
28 
29 } // end of unnamed namespace
30 
31 // *********************** D2CfgContext *************************
32 
33 D2CfgContext::D2CfgContext()
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 
60  ElementPtr d2 = Element::createMap();
61  // Set user-context
62  contextToElement(d2);
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",
77  Element::create(dhcp_ddns::ncrProtocolToString(ncr_protocol)));
78  // Set ncr-format
79  const dhcp_ddns::NameChangeFormat& ncr_format = d2_params_->getNcrFormat();
80  d2->set("ncr-format",
81  Element::create(dhcp_ddns::ncrFormatToString(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
98  ElementPtr result = Element::createMap();
99  result->set("DhcpDdns", d2);
100 
101  return (result);
102 }
103 
104 // *********************** D2CfgMgr *************************
105 
106 const char* D2CfgMgr::IPV4_REV_ZONE_SUFFIX = "in-addr.arpa.";
107 
108 const char* D2CfgMgr::IPV6_REV_ZONE_SUFFIX = "ip6.arpa.";
109 
111 }
112 
114 }
115 
116 ConfigPtr
118  return (ConfigPtr(new D2CfgContext()));
119 }
120 
121 bool
123  // Forward updates are not enabled if no forward servers are defined.
124  return (getD2CfgContext()->getForwardMgr()->size() > 0);
125 }
126 
127 bool
129  // Reverse updates are not enabled if no reverse servers are defined.
130  return (getD2CfgContext()->getReverseMgr()->size() > 0);
131 }
132 
133 bool
134 D2CfgMgr::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 
147 bool
148 D2CfgMgr::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 
158 std::string
159 D2CfgMgr::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 
176 std::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 
206 std::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 
236 const D2ParamsPtr&
238  return (getD2CfgContext()->getD2Params());
239 }
240 
241 std::string
242 D2CfgMgr::getConfigSummary(const uint32_t) {
243  return (getD2Params()->getConfigSummary());
244 }
245 
246 void
248  D2SimpleParser::setAllDefaults(mutable_config);
249 }
250 
252 D2CfgMgr::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
isc::process::ConfigBase
Base class for all configurations.
Definition: config_base.h:31
isc::d2::D2Params
Acts as a storage vault for D2 global scalar parameters.
Definition: d2_config.h:137
isc::process::DCfgMgrBase
Configuration Manager.
Definition: d_cfg_mgr.h:106
isc::d2::DdnsDomainListMgrPtr
boost::shared_ptr< DdnsDomainListMgr > DdnsDomainListMgrPtr
Defines a pointer for DdnsDomain instances.
Definition: d2_cfg_mgr.h:120
LOG_ERROR
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition: macros.h:32
isc::config::CONTROL_RESULT_SUCCESS
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
Definition: command_interpreter.h:39
isc::d2::d2_logger
isc::log::Logger d2_logger("dhcpddns")
Defines the logger used within D2.
Definition: d2_log.h:18
isc::config::createAnswer
ConstElementPtr createAnswer(const int status_code, const std::string &text, const ConstElementPtr &arg)
Definition: command_interpreter.cc:33
isc::d2::DdnsDomainListMgr
Provides storage for and management of a list of DNS domains.
Definition: d2_config.h:608
isc::config
Definition: command_interpreter.cc:23
isc::d2::D2CfgMgr::parse
virtual isc::data::ConstElementPtr parse(isc::data::ConstElementPtr config, bool check_only)
Parses configuration of the D2.
Definition: d2_cfg_mgr.cc:252
isc::d2::D2CfgMgr::D2CfgMgr
D2CfgMgr()
Constructor.
Definition: d2_cfg_mgr.cc:110
isc::config::CONTROL_RESULT_ERROR
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
Definition: command_interpreter.h:42
isc::data
Definition: cfg_to_element.h:25
isc::d2::D2CfgMgr::reverseV6Address
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
isc::Exception
This is a base class for exceptions thrown from the DNS library module.
Definition: exceptions/exceptions.h:23
isc::d2::D2CfgMgr::getD2Params
const D2ParamsPtr & getD2Params()
Convenience method fetches the D2Params from context.
Definition: d2_cfg_mgr.cc:237
isc::d2::D2CfgError
Exception thrown when the error during configuration handling occurs.
Definition: d2_config.h:130
isc::process::ConfigPtr
boost::shared_ptr< ConfigBase > ConfigPtr
Non-const pointer to the SrvConfig.
Definition: config_base.h:119
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::d2::D2CfgMgr::matchReverse
bool matchReverse(const std::string &ip_address, DdnsDomainPtr &domain)
Matches a given IP address to a reverse domain.
Definition: d2_cfg_mgr.cc:148
isc::d2::D2CfgMgr::reverseV4Address
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
isc::d2::D2CfgMgr::getD2CfgContext
D2CfgContextPtr getD2CfgContext()
Convenience method that returns the D2 configuration context.
Definition: d2_cfg_mgr.h:149
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition: exceptions/exceptions.cc:32
hex.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::d2::D2CfgMgr::createNewContext
virtual process::ConfigPtr createNewContext()
Creates an new, blank D2CfgContext context.
Definition: d2_cfg_mgr.cc:117
isc::d2::D2CfgMgr::setCfgDefaults
virtual void setCfgDefaults(isc::data::ElementPtr mutable_config)
Adds default values to the given config.
Definition: d2_cfg_mgr.cc:247
d2_cfg_mgr.h
isc::d2::D2ParamsPtr
boost::shared_ptr< D2Params > D2ParamsPtr
Defines a pointer for D2Params instances.
Definition: d2_config.h:251
command_interpreter.h
isc::d2::D2SimpleParser::setAllDefaults
static size_t setAllDefaults(data::ElementPtr global)
Sets all defaults for D2 configuration.
Definition: d2_simple_parser.cc:118
isc::d2::D2CfgMgr::~D2CfgMgr
virtual ~D2CfgMgr()
Destructor.
Definition: d2_cfg_mgr.cc:113
isc::d2::D2CfgContext::~D2CfgContext
virtual ~D2CfgContext()
Destructor.
Definition: d2_cfg_mgr.cc:55
isc::d2::D2CfgMgr::matchForward
bool matchForward(const std::string &fqdn, DdnsDomainPtr &domain)
Matches a given FQDN to a forward domain.
Definition: d2_cfg_mgr.cc:134
isc::d2::D2CfgContext::toElement
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: d2_cfg_mgr.cc:59
isc::d2::D2CfgContext::D2CfgContext
D2CfgContext()
Constructor.
Definition: d2_cfg_mgr.cc:33
isc::process
Definition: config_base.cc:16
isc::data::UserContext::contextToElement
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition: user_context.cc:15
isc::d2::D2CfgMgr::IPV4_REV_ZONE_SUFFIX
static const char * IPV4_REV_ZONE_SUFFIX
Reverse zone suffix added to IPv4 addresses for reverse lookups.
Definition: d2_cfg_mgr.h:134
isc::d2::TSIGKeyInfoMap
std::map< std::string, TSIGKeyInfoPtr > TSIGKeyInfoMap
Defines a map of TSIGKeyInfos, keyed by the name.
Definition: d2_config.h:401
isc::d2::D2CfgMgr::forwardUpdatesEnabled
bool forwardUpdatesEnabled()
Returns whether or not forward updates are enabled.
Definition: d2_cfg_mgr.cc:122
isc::d2::D2CfgContext
DHCP-DDNS Configuration Context.
Definition: d2_cfg_mgr.h:33
isc::dhcp_ddns::ncrProtocolToString
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition: ncr_io.cc:30
isc::util::encode::encodeHex
string encodeHex(const vector< uint8_t > &binary)
Encode binary data in the base16 ('hex') format.
Definition: base_n.cc:461
isc::d2::D2SimpleParser
Definition: d2_simple_parser.h:22
isc::d2::D2CfgMgr::reverseIpAddress
static std::string reverseIpAddress(const std::string &address)
Generate a reverse order string for the given IP address.
Definition: d2_cfg_mgr.cc:159
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
isc::d2::D2CfgMgr::getConfigSummary
virtual std::string getConfigSummary(const uint32_t selection)
Returns configuration summary in the textual format.
Definition: d2_cfg_mgr.cc:242
isc::d2::D2CfgContextPtr
boost::shared_ptr< D2CfgContext > D2CfgContextPtr
Pointer to a configuration context.
Definition: d2_cfg_mgr.h:22
d2_simple_parser.h
isc::d2::D2CfgMgr::reverseUpdatesEnabled
bool reverseUpdatesEnabled()
Returns whether or not reverse updates are enabled.
Definition: d2_cfg_mgr.cc:128
isc::d2::DdnsDomainPtr
boost::shared_ptr< DdnsDomain > DdnsDomainPtr
Defines a pointer for DdnsDomain instances.
Definition: d2_config.h:586
isc::d2::D2SimpleParser::parse
void parse(const D2CfgContextPtr &ctx, const isc::data::ConstElementPtr &config, bool check_only)
Parses the whole D2 configuration.
Definition: d2_simple_parser.cc:195
isc::dhcp_ddns::ncrFormatToString
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition: ncr_msg.cc:36
isc::d2::D2CfgMgr::IPV6_REV_ZONE_SUFFIX
static const char * IPV6_REV_ZONE_SUFFIX
Reverse zone suffix added to IPv6 addresses for reverse lookups.
Definition: d2_cfg_mgr.h:138
d2_log.h
isc::dhcp_ddns::NameChangeFormat
NameChangeFormat
Defines the list of data wire formats supported.
Definition: ncr_msg.h:60
isc::dhcp_ddns::NameChangeProtocol
NameChangeProtocol
Defines the list of socket protocols supported.
Definition: ncr_io.h:66