Kea  1.5.0
srv_config.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 #include <dhcpsrv/cfgmgr.h>
9 #include <dhcpsrv/srv_config.h>
11 #include <dhcpsrv/cfg_hosts_util.h>
12 #include <process/logging_info.h>
13 #include <log/logger_manager.h>
15 #include <dhcp/pkt.h> // Needed for HWADDR_SOURCE_*
16 #include <list>
17 #include <sstream>
18 
19 using namespace isc::log;
20 using namespace isc::data;
21 using namespace isc::process;
22 
23 namespace isc {
24 namespace dhcp {
25 
26 SrvConfig::SrvConfig()
27  : sequence_(0), cfg_iface_(new CfgIface()),
28  cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
29  cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
30  cfg_shared_networks4_(new CfgSharedNetworks4()),
31  cfg_shared_networks6_(new CfgSharedNetworks6()),
32  cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
33  cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()),
34  cfg_db_access_(new CfgDbAccess()),
35  cfg_host_operations4_(CfgHostOperations::createConfig4()),
36  cfg_host_operations6_(CfgHostOperations::createConfig6()),
37  class_dictionary_(new ClientClassDictionary()),
38  decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0),
39  d2_client_config_(new D2ClientConfig()),
40  configured_globals_(Element::createMap()),
41  cfg_consist_(new CfgConsistency()),
42  server_tag_("") {
43 }
44 
45 SrvConfig::SrvConfig(const uint32_t sequence)
46  : sequence_(sequence), cfg_iface_(new CfgIface()),
47  cfg_option_def_(new CfgOptionDef()), cfg_option_(new CfgOption()),
48  cfg_subnets4_(new CfgSubnets4()), cfg_subnets6_(new CfgSubnets6()),
49  cfg_shared_networks4_(new CfgSharedNetworks4()),
50  cfg_shared_networks6_(new CfgSharedNetworks6()),
51  cfg_hosts_(new CfgHosts()), cfg_rsoo_(new CfgRSOO()),
52  cfg_expiration_(new CfgExpiration()), cfg_duid_(new CfgDUID()),
53  cfg_db_access_(new CfgDbAccess()),
54  cfg_host_operations4_(CfgHostOperations::createConfig4()),
55  cfg_host_operations6_(CfgHostOperations::createConfig6()),
56  class_dictionary_(new ClientClassDictionary()),
57  decline_timer_(0), echo_v4_client_id_(true), dhcp4o6_port_(0),
58  d2_client_config_(new D2ClientConfig()),
59  configured_globals_(Element::createMap()),
60  cfg_consist_(new CfgConsistency()),
61  server_tag_("") {
62 }
63 
64 std::string
65 SrvConfig::getConfigSummary(const uint32_t selection) const {
66  std::ostringstream s;
67  size_t subnets_num;
68  if ((selection & CFGSEL_SUBNET4) == CFGSEL_SUBNET4) {
69  subnets_num = getCfgSubnets4()->getAll()->size();
70  if (subnets_num > 0) {
71  s << "added IPv4 subnets: " << subnets_num;
72  } else {
73  s << "no IPv4 subnets!";
74  }
75  s << "; ";
76  }
77 
78  if ((selection & CFGSEL_SUBNET6) == CFGSEL_SUBNET6) {
79  subnets_num = getCfgSubnets6()->getAll()->size();
80  if (subnets_num > 0) {
81  s << "added IPv6 subnets: " << subnets_num;
82  } else {
83  s << "no IPv6 subnets!";
84  }
85  s << "; ";
86  }
87 
88  if ((selection & CFGSEL_DDNS) == CFGSEL_DDNS) {
89  bool ddns_enabled = getD2ClientConfig()->getEnableUpdates();
90  s << "DDNS: " << (ddns_enabled ? "enabled" : "disabled") << "; ";
91  }
92 
93  if (s.tellp() == static_cast<std::streampos>(0)) {
94  s << "no config details available";
95  }
96 
97  std::string summary = s.str();
98  size_t last_separator_pos = summary.find_last_of(";");
99  if (last_separator_pos == summary.length() - 2) {
100  summary.erase(last_separator_pos);
101  }
102  return (summary);
103 }
104 
105 bool
107  return (getSequence() == other.getSequence());
108 }
109 
110 void
111 SrvConfig::copy(SrvConfig& new_config) const {
112  ConfigBase::copy(new_config);
113 
114  // Replace interface configuration.
115  new_config.cfg_iface_.reset(new CfgIface(*cfg_iface_));
116  // Replace option definitions.
117  cfg_option_def_->copyTo(*new_config.cfg_option_def_);
118  cfg_option_->copyTo(*new_config.cfg_option_);
119  // Replace the client class dictionary
120  new_config.class_dictionary_.reset(new ClientClassDictionary(*class_dictionary_));
121  // Replace the D2 client configuration
122  new_config.setD2ClientConfig(getD2ClientConfig());
123  // Replace configured hooks libraries.
124  new_config.hooks_config_.clear();
125  using namespace isc::hooks;
126  for (HookLibsCollection::const_iterator it =
127  hooks_config_.get().begin();
128  it != hooks_config_.get().end(); ++it) {
129  new_config.hooks_config_.add(it->first, it->second);
130  }
131 }
132 
133 bool
134 SrvConfig::equals(const SrvConfig& other) const {
135 
136  // Checks common elements: logging & config control
137  if (!ConfigBase::equals(other)) {
138  return (false);
139  }
140 
141  // Common information is equal between objects, so check other values.
142  if ((*cfg_iface_ != *other.cfg_iface_) ||
143  (*cfg_option_def_ != *other.cfg_option_def_) ||
144  (*cfg_option_ != *other.cfg_option_) ||
145  (*class_dictionary_ != *other.class_dictionary_) ||
146  (*d2_client_config_ != *other.d2_client_config_)) {
147  return (false);
148  }
149  // Now only configured hooks libraries can differ.
150  // If number of configured hooks libraries are different, then
151  // configurations aren't equal.
152  if (hooks_config_.get().size() != other.hooks_config_.get().size()) {
153  return (false);
154  }
155  // Pass through all configured hooks libraries.
156  return (hooks_config_.equal(other.hooks_config_));
157 }
158 
159 void
161 
162  // Removes statistics for v4 and v6 subnets
163  getCfgSubnets4()->removeStatistics();
164 
165  getCfgSubnets6()->removeStatistics();
166 }
167 
168 void
170  // Updating subnet statistics involves updating lease statistics, which
171  // is done by the LeaseMgr. Since servers with subnets, must have a
172  // LeaseMgr, we do not bother updating subnet stats for servers without
173  // a lease manager, such as D2. @todo We should probably examine why
174  // "SrvConfig" is being used by D2.
176  // Updates statistics for v4 and v6 subnets
177  getCfgSubnets4()->updateStatistics();
178 
179  getCfgSubnets6()->updateStatistics();
180  }
181 }
182 
183 void
185  if (config->getType() != Element::map) {
186  isc_throw(BadValue, "extractConfiguredGlobals must be given a map element");
187  }
188 
189  const std::map<std::string, ConstElementPtr>& values = config->mapValue();
190  for (auto value = values.begin(); value != values.end(); ++value) {
191  if (value->second->getType() != Element::list &&
192  value->second->getType() != Element::map) {
193  addConfiguredGlobal(value->first, value->second);
194  }
195  }
196 }
197 
200  // Toplevel map
201  ElementPtr result = ConfigBase::toElement();
202 
203  // Get family for the configuration manager
204  uint16_t family = CfgMgr::instance().getFamily();
205  // DhcpX global map
206  ElementPtr dhcp = Element::createMap();
207 
208  // Add in explicitly configured globals.
209  dhcp->setValue(configured_globals_->mapValue());
210 
211  // Set user-context
212  contextToElement(dhcp);
213 
214  // Set decline-probation-period
215  dhcp->set("decline-probation-period",
216  Element::create(static_cast<long long>(decline_timer_)));
217  // Set echo-client-id (DHCPv4)
218  if (family == AF_INET) {
219  dhcp->set("echo-client-id", Element::create(echo_v4_client_id_));
220  }
221  // Set dhcp4o6-port
222  dhcp->set("dhcp4o6-port",
223  Element::create(static_cast<int>(dhcp4o6_port_)));
224 
225  // Set dhcp-ddns
226  dhcp->set("dhcp-ddns", d2_client_config_->toElement());
227  // Set interfaces-config
228  dhcp->set("interfaces-config", cfg_iface_->toElement());
229  // Set option-def
230  dhcp->set("option-def", cfg_option_def_->toElement());
231  // Set option-data
232  dhcp->set("option-data", cfg_option_->toElement());
233 
234  // Set subnets and shared networks.
235 
236  // We have two problems to solve:
237  // - a subnet is unparsed once:
238  // * if it is a plain subnet in the global subnet list
239  // * if it is a member of a shared network in the shared network
240  // subnet list
241  // - unparsed subnets must be kept to add host reservations in them.
242  // Of course this can be done only when subnets are unparsed.
243 
244  // The list of all unparsed subnets
245  std::vector<ElementPtr> sn_list;
246 
247  if (family == AF_INET) {
248  // Get plain subnets
249  ElementPtr plain_subnets = Element::createList();
250  const Subnet4Collection* subnets = cfg_subnets4_->getAll();
251  for (Subnet4Collection::const_iterator subnet = subnets->cbegin();
252  subnet != subnets->cend(); ++subnet) {
253  // Skip subnets which are in a shared-network
254  SharedNetwork4Ptr network;
255  (*subnet)->getSharedNetwork(network);
256  if (network) {
257  continue;
258  }
259  ElementPtr subnet_cfg = (*subnet)->toElement();
260  sn_list.push_back(subnet_cfg);
261  plain_subnets->add(subnet_cfg);
262  }
263  dhcp->set("subnet4", plain_subnets);
264 
265  // Get shared networks
266  ElementPtr shared_networks = cfg_shared_networks4_->toElement();
267  dhcp->set("shared-networks", shared_networks);
268 
269  // Get subnets in shared network subnet lists
270  const std::vector<ElementPtr> networks = shared_networks->listValue();
271  for (auto network = networks.cbegin();
272  network != networks.cend(); ++network) {
273  const std::vector<ElementPtr> sh_list =
274  (*network)->get("subnet4")->listValue();
275  for (auto subnet = sh_list.cbegin();
276  subnet != sh_list.cend(); ++subnet) {
277  sn_list.push_back(*subnet);
278  }
279  }
280 
281  } else {
282  // Get plain subnets
283  ElementPtr plain_subnets = Element::createList();
284  const Subnet6Collection* subnets = cfg_subnets6_->getAll();
285  for (Subnet6Collection::const_iterator subnet = subnets->cbegin();
286  subnet != subnets->cend(); ++subnet) {
287  // Skip subnets which are in a shared-network
288  SharedNetwork6Ptr network;
289  (*subnet)->getSharedNetwork(network);
290  if (network) {
291  continue;
292  }
293  ElementPtr subnet_cfg = (*subnet)->toElement();
294  sn_list.push_back(subnet_cfg);
295  plain_subnets->add(subnet_cfg);
296  }
297  dhcp->set("subnet6", plain_subnets);
298 
299  // Get shared networks
300  ElementPtr shared_networks = cfg_shared_networks6_->toElement();
301  dhcp->set("shared-networks", shared_networks);
302 
303  // Get subnets in shared network subnet lists
304  const std::vector<ElementPtr> networks = shared_networks->listValue();
305  for (auto network = networks.cbegin();
306  network != networks.cend(); ++network) {
307  const std::vector<ElementPtr> sh_list =
308  (*network)->get("subnet6")->listValue();
309  for (auto subnet = sh_list.cbegin();
310  subnet != sh_list.cend(); ++subnet) {
311  sn_list.push_back(*subnet);
312  }
313  }
314  }
315 
316  // Host reservations
317  CfgHostsList resv_list;
318  resv_list.internalize(cfg_hosts_->toElement());
319 
320  // Insert global reservations
321  ConstElementPtr global_resvs = resv_list.get(SUBNET_ID_GLOBAL);
322  if (global_resvs->size() > 0) {
323  dhcp->set("reservations", global_resvs);
324  }
325 
326  // Insert subnet reservations
327  for (std::vector<ElementPtr>::const_iterator subnet = sn_list.cbegin();
328  subnet != sn_list.cend(); ++subnet) {
329  ConstElementPtr id = (*subnet)->get("id");
330  if (isNull(id)) {
331  isc_throw(ToElementError, "subnet has no id");
332  }
333  SubnetID subnet_id = id->intValue();
334  ConstElementPtr resvs = resv_list.get(subnet_id);
335  (*subnet)->set("reservations", resvs);
336  }
337 
338  // Set expired-leases-processing
339  ConstElementPtr expired = cfg_expiration_->toElement();
340  dhcp->set("expired-leases-processing", expired);
341  if (family == AF_INET6) {
342  // Set server-id (DHCPv6)
343  dhcp->set("server-id", cfg_duid_->toElement());
344 
345  // Set relay-supplied-options (DHCPv6)
346  dhcp->set("relay-supplied-options", cfg_rsoo_->toElement());
347  }
348  // Set lease-database
349  CfgLeaseDbAccess lease_db(*cfg_db_access_);
350  dhcp->set("lease-database", lease_db.toElement());
351  // Set hosts-databases
352  CfgHostDbAccess host_db(*cfg_db_access_);
353  ConstElementPtr hosts_databases = host_db.toElement();
354  if (hosts_databases->size() > 0) {
355  dhcp->set("hosts-databases", hosts_databases);
356  }
357  // Set host-reservation-identifiers
358  ConstElementPtr host_ids;
359  if (family == AF_INET) {
360  host_ids = cfg_host_operations4_->toElement();
361  } else {
362  host_ids = cfg_host_operations6_->toElement();
363  }
364  dhcp->set("host-reservation-identifiers", host_ids);
365  // Set mac-sources (DHCPv6)
366  if (family == AF_INET6) {
367  dhcp->set("mac-sources", cfg_mac_source_.toElement());
368  }
369  // Set control-socket (skip if null as empty is not legal)
370  if (!isNull(control_socket_)) {
371  dhcp->set("control-socket", UserContext::toElement(control_socket_));
372  }
373  // Set client-classes
374  ConstElementPtr client_classes = class_dictionary_->toElement();
375  // @todo accept empty list
376  if (!client_classes->empty()) {
377  dhcp->set("client-classes", client_classes);
378  }
379  // Set hooks-libraries
380  ConstElementPtr hooks_libs = hooks_config_.toElement();
381  dhcp->set("hooks-libraries", hooks_libs);
382  // Set DhcpX
383  result->set(family == AF_INET ? "Dhcp4" : "Dhcp6", dhcp);
384 
385  ConstElementPtr cfg_consist = cfg_consist_->toElement();
386  dhcp->set("sanity-checks", cfg_consist);
387 
388  // Set config-control (if it exists)
390  if (info) {
391  ConstElementPtr info_elem = info->toElement();
392  dhcp->set("config-control", info_elem);
393  }
394 
395  // Set dhcp-packet-control (if it exists)
396  data::ConstElementPtr dhcp_queue_control = getDHCPQueueControl();
397  if (dhcp_queue_control) {
398  dhcp->set("dhcp-queue-control", dhcp_queue_control);
399  }
400 
401  return (result);
402 }
403 
404 }
405 }
Represents configuration of the RSOO options for the DHCP server.
Definition: cfg_rsoo.h:25
D2ClientConfigPtr getD2ClientConfig()
Returns pointer to the D2 client configuration.
Definition: srv_config.h:544
void internalize(isc::data::ConstElementPtr list)
Internalize a list Element.
uint32_t getSequence() const
Returns configuration sequence number.
Definition: srv_config.h:106
SrvConfig()
Default constructor.
Definition: srv_config.cc:26
Utility class to represent host reservation configurations internally as a map keyed by subnet IDs,...
Holds subnets configured for the DHCPv6 server.
Definition: cfg_subnets6.h:33
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SubnetRandomAccessIndexTag > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > > >> Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:843
Represents configuration of IPv4 shared networks.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
Cannot unparse error.
void removeStatistics()
Removes statistics.
Definition: srv_config.cc:160
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
CfgSubnets6Ptr getCfgSubnets6()
Returns pointer to non-const object holding subnets configuration for DHCPv6.
Definition: srv_config.h:222
Holds configuration parameters pertaining to lease expiration and lease affinity.
bool isNull(ConstElementPtr p)
Checks whether the given ElementPtr is a NULL pointer.
Definition: data.cc:1043
void updateStatistics()
Updates statistics.
Definition: srv_config.cc:169
const isc::data::ConstElementPtr getDHCPQueueControl() const
Returns DHCP queue control information.
Definition: srv_config.h:365
Maintains a list of ClientClassDef's.
process::ConstConfigControlInfoPtr getConfigControlInfo() const
Fetches a read-only copy of the configuration control information.
Definition: config_base.h:82
void clear()
Removes all configured hooks libraries.
Definition: hooks_config.h:59
std::string getConfigSummary(const uint32_t selection) const
Returns summary of the configuration in the textual format.
Definition: srv_config.cc:65
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Parameters for various consistency checks.
Represents option data configuration for the DHCP server.
Definition: cfg_option.h:248
ElementPtr copy(ConstElementPtr from, int level)
Copy the data up to a nesting level.
Definition: data.cc:1114
virtual isc::data::ElementPtr toElement() const
Unparse.
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:53
uint16_t getFamily() const
Returns address family.
Definition: cfgmgr.h:242
void addConfiguredGlobal(const std::string &name, isc::data::ConstElementPtr value)
Adds a parameter to the collection configured globals.
Definition: srv_config.h:570
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
Represents option definitions used by the DHCP server.
Holds access parameters and the configuration of the lease and hosts database connection.
Definition: cfg_db_access.h:25
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition: user_context.cc:15
Represents global configuration for host reservations.
Holds subnets configured for the DHCPv4 server.
Definition: cfg_subnets4.h:32
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
utility class for unparsing
Represents configuration of IPv6 shared networks.
Specifies current DHCP configuration.
Definition: srv_config.h:44
Defines the logger used by the top-level component of kea-dhcp-ddns.
void add(std::string libname, isc::data::ConstElementPtr parameters)
Adds additional hooks libraries.
Definition: hooks_config.h:46
bool equals(const SrvConfig &other) const
Compares two objects for equality.
Definition: srv_config.cc:134
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SubnetRandomAccessIndexTag > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > > >> Subnet4Collection
A collection of Subnet4 objects.
Definition: subnet.h:798
static const uint32_t CFGSEL_SUBNET4
Number of IPv4 subnets.
Definition: srv_config.h:52
const isc::hooks::HookLibsCollection & get() const
Provides access to the configured hooks libraries.
Definition: hooks_config.h:54
bool sequenceEquals(const SrvConfig &other)
Compares configuration sequence with other sequence.
Definition: srv_config.cc:106
void extractConfiguredGlobals(isc::data::ConstElementPtr config)
Saves scalar elements from the global scope of a configuration.
Definition: srv_config.cc:184
The Element class represents a piece of data, used by the command channel and configuration parts.
Definition: data.h:66
Represents the host reservations specified in the configuration file.
Definition: cfg_hosts.h:37
static const uint32_t CFGSEL_DDNS
DDNS enabled/disabled.
Definition: srv_config.h:60
isc::data::ElementPtr toElement() const
Unparse a configuration object.
static bool haveInstance()
Indicates if the lease manager has been instantiated.
CfgSubnets4Ptr getCfgSubnets4()
Returns pointer to non-const object holding subnets configuration for DHCPv4.
Definition: srv_config.h:188
isc::data::ConstElementPtr get(SubnetID id) const
Return the host reservations for a subnet ID.
void copy(SrvConfig &new_config) const
Copies the current configuration to a new configuration.
Definition: srv_config.cc:111
static const uint32_t CFGSEL_SUBNET6
Number of IPv6 subnets.
Definition: srv_config.h:54
virtual isc::data::ElementPtr toElement() const
Unparse.
bool equal(const HooksConfig &other) const
Compares two Hooks Config classes for equality.
Definition: hooks_config.cc:67
Holds manual configuration of the server identifier (DUID).
Definition: cfg_duid.h:30
void setD2ClientConfig(const D2ClientConfigPtr &d2_client_config)
Sets the D2 client configuration.
Definition: srv_config.h:555
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: srv_config.cc:199
boost::shared_ptr< const ConfigControlInfo > ConstConfigControlInfoPtr
Defines a pointer to a const ConfigControlInfo.