Kea 2.5.8
cb_ctl_dhcp6.cc
Go to the documentation of this file.
1// Copyright (C) 2019-2024 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>
9#include <dhcpsrv/cfgmgr.h>
10#include <dhcpsrv/dhcpsrv_log.h>
11#include <dhcpsrv/host_mgr.h>
14#include <hooks/hooks_manager.h>
15#include <boost/foreach.hpp>
16
17using namespace isc::db;
18using namespace isc::data;
19using namespace isc::process;
20using namespace isc::hooks;
21
22namespace {
23
25struct CbCtlHooks {
26 int hook_index_cb6_updated_;
27
29 CbCtlHooks() {
30 hook_index_cb6_updated_ = HooksManager::registerHook("cb6_updated");
31 }
32};
33
34// Declare a Hooks object. As this is outside any function or method, it
35// will be instantiated (and the constructor run) when the module is loaded.
36// As a result, the hook indexes will be defined before any method in this
37// module is called.
38CbCtlHooks hooks_;
39
40}; // anonymous namespace
41
42namespace isc {
43namespace dhcp {
44
45void
47 const db::ServerSelector& server_selector,
48 const boost::posix_time::ptime& lb_modification_time,
49 const db::AuditEntryCollection& audit_entries) {
50 bool globals_fetched = false;
51 auto reconfig = audit_entries.empty();
52 auto cb_update = !reconfig;
53 auto current_cfg = CfgMgr::instance().getCurrentCfg();
54 auto staging_cfg = CfgMgr::instance().getStagingCfg();
55
56 // Let's first delete all the configuration elements for which DELETE audit
57 // entries are found. Although, this may break chronology of the audit in
58 // some cases it should not affect the end result of the data fetch. If the
59 // object was created and then subsequently deleted, we will first try to
60 // delete this object from the local configuration (which will fail because
61 // the object does not exist) and then we will try to fetch it from the
62 // database which will return no result.
63 if (cb_update) {
64
65 auto external_cfg = CfgMgr::instance().createExternalCfg();
66
67 // Get audit entries for deleted global parameters.
68 auto const& index = audit_entries.get<AuditEntryObjectTypeTag>();
69 auto range = index.equal_range(boost::make_tuple("dhcp6_global_parameter",
70 AuditEntry::ModificationType::DELETE));
71 if (range.first != range.second) {
72 // Some globals have been deleted. Since we currently don't track database
73 // identifiers of the global parameters we have to fetch all global
74 // parameters for this server. Next, we simply replace existing
75 // global parameters with the new parameters. This is slightly
76 // inefficient but only slightly. Note that this is a single
77 // database query and the number of global parameters is small.
79 globals = getMgr().getPool()->getAllGlobalParameters6(backend_selector, server_selector);
80 translateAndAddGlobalsToConfig(external_cfg, globals);
81
82 // Add defaults.
83 external_cfg->applyDefaultsConfiguredGlobals(SimpleParser6::GLOBAL6_DEFAULTS);
84
85 // Sanity check it.
86 external_cfg->sanityChecksLifetime("preferred-lifetime");
87 external_cfg->sanityChecksLifetime("valid-lifetime");
88
89 // Now that we successfully fetched the new global parameters, let's
90 // remove existing ones and merge them into the current configuration.
91 current_cfg->clearConfiguredGlobals();
92 CfgMgr::instance().mergeIntoCurrentCfg(external_cfg->getSequence());
93 globals_fetched = true;
94 }
95
96 try {
97 // Get audit entries for deleted option definitions and delete each
98 // option definition from the current configuration for which the
99 // audit entry is found.
100 range = index.equal_range(boost::make_tuple("dhcp6_option_def",
101 AuditEntry::ModificationType::DELETE));
102 BOOST_FOREACH(auto const& entry, range) {
103 current_cfg->getCfgOptionDef()->del(entry->getObjectId());
104 }
105
106 // Repeat the same for other configuration elements.
107
108 range = index.equal_range(boost::make_tuple("dhcp6_options",
109 AuditEntry::ModificationType::DELETE));
110 BOOST_FOREACH(auto const& entry, range) {
111 current_cfg->getCfgOption()->del(entry->getObjectId());
112 }
113
114 range = index.equal_range(boost::make_tuple("dhcp6_client_class",
115 AuditEntry::ModificationType::DELETE));
116 BOOST_FOREACH(auto const& entry, range) {
117 current_cfg->getClientClassDictionary()->removeClass(entry->getObjectId());
118 }
119
120 range = index.equal_range(boost::make_tuple("dhcp6_shared_network",
121 AuditEntry::ModificationType::DELETE));
122 BOOST_FOREACH(auto const& entry, range) {
123 current_cfg->getCfgSharedNetworks6()->del(entry->getObjectId());
124 }
125
126 range = index.equal_range(boost::make_tuple("dhcp6_subnet",
127 AuditEntry::ModificationType::DELETE));
128 BOOST_FOREACH(auto const& entry, range) {
129 // If the deleted subnet belongs to a shared network and the
130 // shared network is not being removed, we need to detach the
131 // subnet from the shared network.
132 auto subnet = current_cfg->getCfgSubnets6()->getBySubnetId(entry->getObjectId());
133 if (subnet) {
134 // Check if the subnet belongs to a shared network.
135 SharedNetwork6Ptr network;
136 subnet->getSharedNetwork(network);
137 if (network) {
138 // Detach the subnet from the shared network.
139 network->del(subnet->getID());
140 }
141 // Actually delete the subnet from the configuration.
142 current_cfg->getCfgSubnets6()->del(entry->getObjectId());
143 }
144 }
145
146 } catch (...) {
147 // Ignore errors thrown when attempting to delete a non-existing
148 // configuration entry. There is no guarantee that the deleted
149 // entry is actually there as we're not processing the audit
150 // chronologically.
151 }
152 }
153
154 // Create the external config into which we'll fetch backend config data.
156
157 // First let's fetch the globals and add them to external config.
158 AuditEntryCollection updated_entries;
159 if (!globals_fetched) {
160 if (cb_update) {
161 updated_entries = fetchConfigElement(audit_entries, "dhcp6_global_parameter");
162 }
163 if (reconfig || !updated_entries.empty()) {
165 globals = getMgr().getPool()->getModifiedGlobalParameters6(backend_selector, server_selector,
166 lb_modification_time);
167 translateAndAddGlobalsToConfig(external_cfg, globals);
168 globals_fetched = true;
169 }
170 }
171
172 // Now we fetch the option definitions and add them.
173 if (cb_update) {
174 updated_entries = fetchConfigElement(audit_entries, "dhcp6_option_def");
175 }
176 if (reconfig || !updated_entries.empty()) {
177 OptionDefContainer option_defs =
178 getMgr().getPool()->getModifiedOptionDefs6(backend_selector, server_selector,
179 lb_modification_time);
180 for (auto const& option_def : option_defs) {
181 if (!audit_entries.empty() && !hasObjectId(updated_entries, option_def->getId())) {
182 continue;
183 }
184 external_cfg->getCfgOptionDef()->add(option_def);
185 }
186 }
187
188 // Next fetch the options. They are returned as a container of OptionDescriptors.
189 if (cb_update) {
190 updated_entries = fetchConfigElement(audit_entries, "dhcp6_options");
191 }
192 if (reconfig || !updated_entries.empty()) {
193 OptionContainer options = getMgr().getPool()->getModifiedOptions6(backend_selector,
194 server_selector,
195 lb_modification_time);
196 for (auto const& option : options) {
197 if (!audit_entries.empty() && !hasObjectId(updated_entries, option.getId())) {
198 continue;
199 }
200 external_cfg->getCfgOption()->add(option, option.space_name_);
201 }
202 }
203
204 // Fetch client classes. They are returned in a ClientClassDictionary.
205 if (cb_update) {
206 updated_entries = fetchConfigElement(audit_entries, "dhcp6_client_class");
207 }
208 if (reconfig || !updated_entries.empty()) {
209 ClientClassDictionary client_classes = getMgr().getPool()->getAllClientClasses6(backend_selector,
210 server_selector);
211 // Match expressions are not initialized for classes returned from the config backend.
212 // We have to ensure to initialize them before they can be used by the server.
213 client_classes.initMatchExpr(AF_INET6);
214
215 // Class options also need to be created when returned from the config backend.
216 client_classes.createOptions(external_cfg->getCfgOptionDef());
217
218 external_cfg->setClientClassDictionary(boost::make_shared<ClientClassDictionary>(client_classes));
219 }
220
221 // Allocator selection at the global level can affect subnets and shared networks
222 // for which the allocator hasn't been specified explicitly. Let's see if the
223 // allocator has been specified at the global level.
224 std::string global_allocator;
225 auto allocator = external_cfg->getConfiguredGlobal(CfgGlobals::ALLOCATOR);
226 if (allocator && (allocator->getType() == Element::string)) {
227 global_allocator = allocator->stringValue();
228 }
229
230 // Also, get the PD allocator.
231 std::string global_pd_allocator;
232 allocator = external_cfg->getConfiguredGlobal(CfgGlobals::PD_ALLOCATOR);
233 if (allocator && (allocator->getType() == Element::string)) {
234 global_pd_allocator = allocator->stringValue();
235 }
236
237 // If we're fetching the changes from the config backend we also want
238 // to see if the global allocator has changed. Let's get the currently
239 // used allocator too.
240 auto allocator_changed = false;
241 // We're only affected by the allocator change if this is the update from
242 // the configuration backend.
243 if (cb_update) {
244 auto allocator = CfgMgr::instance().getCurrentCfg()->getConfiguredGlobal(CfgGlobals::ALLOCATOR);
245 if (allocator && (allocator->getType() == Element::string)) {
246 allocator_changed = (global_allocator != allocator->stringValue());
247 }
248
249 // The address allocator hasn't changed. So, let's check if the PD allocator
250 // has changed.
251 if (!allocator_changed) {
252 auto allocator = CfgMgr::instance().getCurrentCfg()->getConfiguredGlobal(CfgGlobals::PD_ALLOCATOR);
253 if (allocator && (allocator->getType() == Element::string)) {
254 allocator_changed = (global_pd_allocator != allocator->stringValue());
255 }
256 }
257 }
258
259 // Now fetch the shared networks.
260 if (cb_update) {
261 updated_entries = fetchConfigElement(audit_entries, "dhcp6_shared_network");
262 }
264 if (allocator_changed || reconfig) {
265 // A change of the allocator or the server reconfiguration can affect all
266 // shared networks. Get all shared networks.
267 networks = getMgr().getPool()->getAllSharedNetworks6(backend_selector, server_selector);
268 } else if (!updated_entries.empty()) {
269 networks = getMgr().getPool()->getModifiedSharedNetworks6(backend_selector, server_selector,
270 lb_modification_time);
271 }
272 for (auto const& network : networks) {
273 if (!allocator_changed && cb_update && !hasObjectId(updated_entries, network->getId())) {
274 continue;
275 }
276 // In order to take advantage of the dynamic inheritance of global
277 // parameters to a shared network we need to set a callback function
278 // for each network to allow for fetching global parameters.
279 network->setFetchGlobalsFn([] () -> ConstCfgGlobalsPtr {
280 return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
281 });
282 network->setDefaultAllocatorType(global_allocator);
283 network->setDefaultPdAllocatorType(global_pd_allocator);
284 external_cfg->getCfgSharedNetworks6()->add(network);
285 }
286
287 // Next we fetch subnets.
288 if (cb_update) {
289 updated_entries = fetchConfigElement(audit_entries, "dhcp6_subnet");
290 }
291 Subnet6Collection subnets;
292 if (allocator_changed || reconfig) {
293 // A change of the allocator or the server reconfiguration can affect all
294 // subnets. Get all subnets.
295 subnets = getMgr().getPool()->getAllSubnets6(backend_selector, server_selector);
296
297 } else if (!updated_entries.empty()) {
298 // An update from the config backend when the global allocator hasn't changed
299 // means that we only need to handle the modified subnets.
300 subnets = getMgr().getPool()->getModifiedSubnets6(backend_selector,
301 server_selector,
302 lb_modification_time);
303 }
304 // Iterate over all subnets that may require reconfiguration.
305 for (auto const& subnet : subnets) {
306 if (!audit_entries.empty() && !hasObjectId(updated_entries, subnet->getID())) {
307 continue;
308 }
309 // In order to take advantage of the dynamic inheritance of global
310 // parameters to a subnet we need to set a callback function for each
311 // subnet to allow for fetching global parameters.
312 subnet->setFetchGlobalsFn([] () -> ConstCfgGlobalsPtr {
313 return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
314 });
315 subnet->setDefaultAllocatorType(global_allocator);
316 subnet->setDefaultPdAllocatorType(global_pd_allocator);
317 external_cfg->getCfgSubnets6()->add(subnet);
318 }
319
320 if (reconfig) {
321 // If we're configuring the server after startup, we do not apply the
322 // ip-reservations-unique setting here. It will be applied when the
323 // configuration is committed.
324 auto const& cfg = CfgMgr::instance().getStagingCfg();
325 external_cfg->sanityChecksLifetime(*cfg, "preferred-lifetime");
326 external_cfg->sanityChecksLifetime(*cfg, "valid-lifetime");
327 CfgMgr::instance().mergeIntoStagingCfg(external_cfg->getSequence());
328
329 } else {
330 if (globals_fetched) {
331 // ip-reservations-unique parameter requires special handling because
332 // setting it to false may be unsupported by some host backends.
333 bool ip_unique = true;
334 auto ip_unique_param = external_cfg->getConfiguredGlobal("ip-reservations-unique");
335 if (ip_unique_param && (ip_unique_param->getType() == Element::boolean)) {
336 ip_unique = ip_unique_param->boolValue();
337 }
338 // First try to use the new setting to configure the HostMgr because it
339 // may fail if the backend does not support it.
340 if (!HostMgr::instance().setIPReservationsUnique(ip_unique)) {
341 // The new setting is unsupported by the backend, so do not apply this
342 // setting at all.
344 external_cfg->addConfiguredGlobal("ip-reservations-unique", Element::create(true));
345 }
346 }
347 auto const& cfg = CfgMgr::instance().getCurrentCfg();
348 external_cfg->sanityChecksLifetime(*cfg, "preferred-lifetime");
349 external_cfg->sanityChecksLifetime(*cfg, "valid-lifetime");
350 CfgMgr::instance().mergeIntoCurrentCfg(external_cfg->getSequence());
351 CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->initAllocatorsAfterConfigure();
352 }
354
355 if (cb_update &&
356 HooksManager::calloutsPresent(hooks_.hook_index_cb6_updated_)) {
358
359 // Use the RAII wrapper to make sure that the callout handle state is
360 // reset when this object goes out of scope. All hook points must do
361 // it to prevent possible circular dependency between the callout
362 // handle and its arguments.
363 ScopedCalloutHandleState callout_handle_state(callout_handle);
364
365 // Pass a shared pointer to audit entries.
366 AuditEntryCollectionPtr ptr(new AuditEntryCollection(audit_entries));
367 callout_handle->setArgument("audit_entries", ptr);
368
369 // Call the callouts
370 HooksManager::callCallouts(hooks_.hook_index_cb6_updated_, *callout_handle);
371
372 // Ignore the result.
373 }
374}
375
376} // end of namespace isc::dhcp
377} // end of namespace isc
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:249
Config Backend selector.
Server selector for associating objects in a database with specific servers.
void translateAndAddGlobalsToConfig(SrvConfigPtr external_cfg, data::StampedValueCollection &cb_globals) const
It translates the top level map parameters from flat naming format (e.g.
Definition: cb_ctl_dhcp.h:72
virtual void databaseConfigApply(const db::BackendSelector &backend_selector, const db::ServerSelector &server_selector, const boost::posix_time::ptime &lb_modification_time, const db::AuditEntryCollection &audit_entries)
DHCPv6 server specific method to fetch and apply back end configuration into the local configuration.
Definition: cb_ctl_dhcp6.cc:46
SrvConfigPtr createExternalCfg()
Creates an external configuration and returns pointer to it.
Definition: cfgmgr.cc:177
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
void mergeIntoStagingCfg(const uint32_t seq)
Merges external configuration with the given sequence number into the staging configuration.
Definition: cfgmgr.cc:190
void mergeIntoCurrentCfg(const uint32_t seq)
Merges external configuration with the given sequence number into the current configuration.
Definition: cfgmgr.cc:195
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:167
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition: cfgmgr.cc:161
Maintains a list of ClientClassDef's.
void createOptions(const CfgOptionDefPtr &cfg_option_def)
Iterates over the classes in the dictionary and recreates the options.
void initMatchExpr(uint16_t family)
Iterates over the classes in the dictionary and ensures that that match expressions are initialized.
static HostMgr & instance()
Returns a sole instance of the HostMgr.
Definition: host_mgr.cc:114
static const isc::data::SimpleDefaults GLOBAL6_DEFAULTS
This table defines default global values for DHCPv6.
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static boost::shared_ptr< CalloutHandle > createCalloutHandle()
Return callout handle.
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
Wrapper class around callout handle which automatically resets handle's state.
db::AuditEntryCollection fetchConfigElement(const db::AuditEntryCollection &audit_entries, const std::string &object_type) const
Returns audit entries for new or updated configuration elements of specific type to be fetched from t...
Definition: cb_ctl_base.h:270
ConfigBackendMgrType & getMgr() const
Returns the instance of the Config Backend Manager used by this object.
Definition: cb_ctl_base.h:320
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
boost::multi_index_container< StampedValuePtr, boost::multi_index::indexed_by< boost::multi_index::hashed_non_unique< boost::multi_index::tag< StampedValueNameIndexTag >, boost::multi_index::const_mem_fun< StampedValue, std::string, &StampedValue::getName > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< StampedValueModificationTimeIndexTag >, boost::multi_index::const_mem_fun< BaseStampedElement, boost::posix_time::ptime, &BaseStampedElement::getModificationTime > > > > StampedValueCollection
Multi index container for StampedValue.
boost::multi_index_container< AuditEntryPtr, boost::multi_index::indexed_by< boost::multi_index::ordered_non_unique< boost::multi_index::tag< AuditEntryObjectTypeTag >, boost::multi_index::composite_key< AuditEntry, boost::multi_index::const_mem_fun< AuditEntry, std::string, &AuditEntry::getObjectType >, boost::multi_index::const_mem_fun< AuditEntry, AuditEntry::ModificationType, &AuditEntry::getModificationType > > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< AuditEntryModificationTimeIdTag >, boost::multi_index::composite_key< AuditEntry, boost::multi_index::const_mem_fun< AuditEntry, boost::posix_time::ptime, &AuditEntry::getModificationTime >, boost::multi_index::const_mem_fun< AuditEntry, uint64_t, &AuditEntry::getRevisionId > > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< AuditEntryObjectIdTag >, boost::multi_index::const_mem_fun< AuditEntry, uint64_t, &AuditEntry::getObjectId > > > > AuditEntryCollection
Multi index container holding AuditEntry instances.
Definition: audit_entry.h:291
boost::shared_ptr< AuditEntryCollection > AuditEntryCollectionPtr
Definition: audit_entry.h:294
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
boost::shared_ptr< const CfgGlobals > ConstCfgGlobalsPtr
Const shared pointer to a CfgGlobals instance.
Definition: cfg_globals.h:171
boost::multi_index_container< SharedNetwork6Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SharedNetworkRandomAccessIndexTag > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< SharedNetworkIdIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, uint64_t, &data::BaseStampedElement::getId > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SharedNetworkNameIndexTag >, boost::multi_index::const_mem_fun< SharedNetwork6, std::string, &SharedNetwork6::getName > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SharedNetworkModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > SharedNetwork6Collection
Multi index container holding shared networks.
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< 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< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:974
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:1267
const isc::log::MessageID DHCPSRV_CFGMGR_CONFIG6_MERGED
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
boost::multi_index_container< OptionDescriptor, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::hashed_non_unique< KeyFromKeyExtractor< boost::multi_index::const_mem_fun< Option, uint16_t, &Option::getType >, boost::multi_index::member< OptionDescriptor, OptionPtr, &OptionDescriptor::option_ > > >, boost::multi_index::hashed_non_unique< boost::multi_index::member< OptionDescriptor, bool, &OptionDescriptor::persistent_ > >, boost::multi_index::ordered_non_unique< boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< OptionIdIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, uint64_t, &data::BaseStampedElement::getId > >, boost::multi_index::hashed_non_unique< boost::multi_index::member< OptionDescriptor, bool, &OptionDescriptor::cancelled_ > > > > OptionContainer
Multi index container for DHCP option descriptors.
Definition: cfg_option.h:300
boost::multi_index_container< OptionDefinitionPtr, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::hashed_non_unique< boost::multi_index::const_mem_fun< OptionDefinition, uint16_t, &OptionDefinition::getCode > >, boost::multi_index::hashed_non_unique< boost::multi_index::const_mem_fun< OptionDefinition, std::string, &OptionDefinition::getName > >, boost::multi_index::ordered_non_unique< boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::StampedElement::getModificationTime > >, boost::multi_index::hashed_non_unique< boost::multi_index::tag< OptionIdIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, uint64_t, &data::BaseStampedElement::getId > > > > OptionDefContainer
Multi index container for DHCP option definitions.
const isc::log::MessageID DHCPSRV_CFGMGR_IPV6_RESERVATIONS_NON_UNIQUE_IGNORED
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
bool hasObjectId(const db::AuditEntryCollection &audit_entries, const uint64_t &object_id)
Checks if an object is in a collection od audit entries.
Definition: cb_ctl_base.h:372
Defines the logger used by the top-level component of kea-lfc.
Tag used to access index by object type.
Definition: audit_entry.h:229