Kea 1.5.0
host_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#include <dhcpsrv/cfg_hosts.h>
9#include <dhcpsrv/cfgmgr.h>
10#include <dhcpsrv/host_mgr.h>
11#include <dhcpsrv/hosts_log.h>
13
14namespace {
15
22isc::dhcp::ConstCfgHostsPtr getCfgHosts() {
23 return (isc::dhcp::CfgMgr::instance().getCurrentCfg()->getCfgHosts());
24}
25
26} // end of anonymous namespace
27
28namespace isc {
29namespace dhcp {
30
31using namespace isc::asiolink;
32
33boost::scoped_ptr<HostMgr>&
34HostMgr::getHostMgrPtr() {
35 static boost::scoped_ptr<HostMgr> host_mgr_ptr;
36 return (host_mgr_ptr);
37}
38
39void
41 getHostMgrPtr().reset(new HostMgr());
42}
43
44void
45HostMgr::addBackend(const std::string& access) {
46 HostDataSourceFactory::add(getHostMgrPtr()->alternate_sources_, access);
47}
48
49bool
50HostMgr::delBackend(const std::string& db_type) {
51 return (HostDataSourceFactory::del(getHostMgrPtr()->alternate_sources_, db_type));
52}
53
54void
56 getHostMgrPtr()->alternate_sources_.clear();
57}
58
61 if (alternate_sources_.empty()) {
62 return (HostDataSourcePtr());
63 }
64 return (alternate_sources_[0]);
65}
66
67bool
69 if (getHostMgrPtr()->cache_ptr_) {
70 return (true);
71 }
72 HostDataSourceList& sources = getHostMgrPtr()->alternate_sources_;
73 if (sources.empty()) {
74 return (false);
75 }
76 CacheHostDataSourcePtr cache_ptr =
77 boost::dynamic_pointer_cast<CacheHostDataSource>(sources[0]);
78 if (cache_ptr) {
79 getHostMgrPtr()->cache_ptr_ = cache_ptr;
80 if (logging) {
81 LOG_INFO(hosts_logger, HOSTS_CFG_CACHE_HOST_DATA_SOURCE)
82 .arg(cache_ptr->getType());
83 }
84 return (true);
85 }
86 return (false);
87}
88
91 boost::scoped_ptr<HostMgr>& host_mgr_ptr = getHostMgrPtr();
92 if (!host_mgr_ptr) {
93 create();
94 }
95 return (*host_mgr_ptr);
96}
97
100 const uint8_t* identifier_begin,
101 const size_t identifier_len) const {
102 ConstHostCollection hosts = getCfgHosts()->getAll(identifier_type,
103 identifier_begin,
104 identifier_len);
105 for (auto source : alternate_sources_) {
106 ConstHostCollection hosts_plus =
107 source->getAll(identifier_type, identifier_begin, identifier_len);
108 hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
109 }
110 return (hosts);
111}
112
113
115HostMgr::getAll4(const IOAddress& address) const {
116 ConstHostCollection hosts = getCfgHosts()->getAll4(address);
117 for (auto source : alternate_sources_) {
118 ConstHostCollection hosts_plus = source->getAll4(address);
119 hosts.insert(hosts.end(), hosts_plus.begin(), hosts_plus.end());
120 }
121 return (hosts);
122}
123
125HostMgr::get4Any(const SubnetID& subnet_id,
126 const Host::IdentifierType& identifier_type,
127 const uint8_t* identifier_begin,
128 const size_t identifier_len) const {
129 ConstHostPtr host = getCfgHosts()->get4(subnet_id, identifier_type,
130 identifier_begin, identifier_len);
131
132 // Found it in the config file or there are no backends configured?
133 // Then we're done here.
134 if (host || alternate_sources_.empty()) {
135 return (host);
136 }
137
139 HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER)
140 .arg(subnet_id)
141 .arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
142 identifier_len));
143
144 // Try to find a host in each configured backend. We return as soon
145 // as we find first hit.
146 for (auto source : alternate_sources_) {
147 host = source->get4(subnet_id, identifier_type,
148 identifier_begin, identifier_len);
149
150 if (host) {
152 HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_HOST)
153 .arg(subnet_id)
154 .arg(Host::getIdentifierAsText(identifier_type,
155 identifier_begin,
156 identifier_len))
157 .arg(source->getType())
158 .arg(host->toText());
159
160 if (source != cache_ptr_) {
161 cache(host);
162 }
163 return (host);
164 }
165 }
167 HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_IDENTIFIER_NULL)
168 .arg(subnet_id)
169 .arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
170 identifier_len));
171 return (ConstHostPtr());
172}
173
175HostMgr::get4(const SubnetID& subnet_id,
176 const Host::IdentifierType& identifier_type,
177 const uint8_t* identifier_begin,
178 const size_t identifier_len) const {
179 ConstHostPtr host = get4Any(subnet_id, identifier_type,
180 identifier_begin, identifier_len);
181 if (host && host->getNegative()) {
182 return (ConstHostPtr());
183 } else if (!host && negative_caching_) {
184 cacheNegative(subnet_id, SubnetID(SUBNET_ID_UNUSED),
185 identifier_type, identifier_begin, identifier_len);
186 }
187 return (host);
188}
189
191HostMgr::get4(const SubnetID& subnet_id,
192 const asiolink::IOAddress& address) const {
193 ConstHostPtr host = getCfgHosts()->get4(subnet_id, address);
194 if (host || alternate_sources_.empty()) {
195 return (host);
196 }
198 HOSTS_MGR_ALTERNATE_GET4_SUBNET_ID_ADDRESS4)
199 .arg(subnet_id)
200 .arg(address.toText());
201 for (auto source : alternate_sources_) {
202 host = source->get4(subnet_id, address);
203 if (host && host->getNegative()) {
204 return (ConstHostPtr());
205 }
206 if (host && source != cache_ptr_) {
207 cache(host);
208 }
209 if (host) {
210 return (host);
211 }
212 }
213 return (ConstHostPtr());
214}
215
216
218HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
219 ConstHostPtr host = getCfgHosts()->get6(prefix, prefix_len);
220 if (host || alternate_sources_.empty()) {
221 return (host);
222 }
223 LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_MGR_ALTERNATE_GET6_PREFIX)
224 .arg(prefix.toText())
225 .arg(static_cast<int>(prefix_len));
226 for (auto source : alternate_sources_) {
227 host = source->get6(prefix, prefix_len);
228 if (host && host->getNegative()) {
229 return (ConstHostPtr());
230 }
231 if (host && source != cache_ptr_) {
232 cache(host);
233 }
234 if (host) {
235 return (host);
236 }
237 }
238 return (ConstHostPtr());
239}
240
242HostMgr::get6Any(const SubnetID& subnet_id,
243 const Host::IdentifierType& identifier_type,
244 const uint8_t* identifier_begin,
245 const size_t identifier_len) const {
246 ConstHostPtr host = getCfgHosts()->get6(subnet_id, identifier_type,
247 identifier_begin, identifier_len);
248 if (host || alternate_sources_.empty()) {
249 return (host);
250 }
251
253 HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER)
254 .arg(subnet_id)
255 .arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
256 identifier_len));
257
258 for (auto source : alternate_sources_) {
259 host = source->get6(subnet_id, identifier_type,
260 identifier_begin, identifier_len);
261
262 if (host) {
264 HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_HOST)
265 .arg(subnet_id)
266 .arg(Host::getIdentifierAsText(identifier_type,
267 identifier_begin,
268 identifier_len))
269 .arg(source->getType())
270 .arg(host->toText());
271
272 if (source != cache_ptr_) {
273 cache(host);
274 }
275 return (host);
276 }
277 }
278
280 HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_IDENTIFIER_NULL)
281 .arg(subnet_id)
282 .arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
283 identifier_len));
284
285 return (ConstHostPtr());
286}
287
289HostMgr::get6(const SubnetID& subnet_id,
290 const Host::IdentifierType& identifier_type,
291 const uint8_t* identifier_begin,
292 const size_t identifier_len) const {
293 ConstHostPtr host = get6Any(subnet_id, identifier_type,
294 identifier_begin, identifier_len);
295 if (host && host->getNegative()) {
296 return (ConstHostPtr());
297 } else if (!host && negative_caching_) {
298 cacheNegative(SubnetID(SUBNET_ID_UNUSED), subnet_id,
299 identifier_type, identifier_begin, identifier_len);
300 }
301 return (host);
302}
303
305HostMgr::get6(const SubnetID& subnet_id,
306 const asiolink::IOAddress& addr) const {
307 ConstHostPtr host = getCfgHosts()->get6(subnet_id, addr);
308 if (host || alternate_sources_.empty()) {
309 return (host);
310 }
312 HOSTS_MGR_ALTERNATE_GET6_SUBNET_ID_ADDRESS6)
313 .arg(subnet_id)
314 .arg(addr.toText());
315 for (auto source : alternate_sources_) {
316 host = source->get6(subnet_id, addr);
317 if (host && host->getNegative()) {
318 return (ConstHostPtr());
319 }
320 if (host && source != cache_ptr_) {
321 cache(host);
322 }
323 if (host) {
324 return (host);
325 }
326 }
327 return (ConstHostPtr());
328}
329
330void
331HostMgr::add(const HostPtr& host) {
332 if (alternate_sources_.empty()) {
333 isc_throw(NoHostDataSourceManager, "Unable to add new host because there is "
334 "no hosts-database configured.");
335 }
336 for (auto source : alternate_sources_) {
337 source->add(host);
338 }
339 // If no backend throws the host should be cached.
340 if (cache_ptr_) {
341 cache(host);
342 }
343}
344
345bool
346HostMgr::del(const SubnetID& subnet_id, const asiolink::IOAddress& addr) {
347 if (alternate_sources_.empty()) {
348 isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
349 "no hosts-database configured.");
350 }
351
352 for (auto source : alternate_sources_) {
353 if (source->del(subnet_id, addr)) {
354 return (true);
355 }
356 }
357 return (false);
358}
359
360bool
361HostMgr::del4(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
362 const uint8_t* identifier_begin, const size_t identifier_len) {
363 if (alternate_sources_.empty()) {
364 isc_throw(NoHostDataSourceManager, "Unable to delete a host because there is "
365 "no hosts-database configured.");
366 }
367
368 for (auto source : alternate_sources_) {
369 if (source->del4(subnet_id, identifier_type,
370 identifier_begin, identifier_len)) {
371 return (true);
372 }
373 }
374 return (false);
375}
376
377bool
378HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
379 const uint8_t* identifier_begin, const size_t identifier_len) {
380 if (alternate_sources_.empty()) {
381 isc_throw(NoHostDataSourceManager, "unable to delete a host because there is "
382 "no alternate host data source present");
383 }
384
385 for (auto source : alternate_sources_) {
386 if (source->del6(subnet_id, identifier_type,
387 identifier_begin, identifier_len)) {
388 return (true);
389 }
390 }
391 return (false);
392}
393
394void
396 if (cache_ptr_) {
397 // Need a real host.
398 if (!host || host->getNegative()) {
399 return;
400 }
401 // Replace any existing value.
402 // Don't check the result as it does not matter?
403 cache_ptr_->insert(host, true);
404 }
405}
406
407void
408HostMgr::cacheNegative(const SubnetID& ipv4_subnet_id,
409 const SubnetID& ipv6_subnet_id,
410 const Host::IdentifierType& identifier_type,
411 const uint8_t* identifier_begin,
412 const size_t identifier_len) const {
413 if (cache_ptr_ && negative_caching_) {
414 HostPtr host(new Host(identifier_begin, identifier_len,
415 identifier_type,
416 ipv4_subnet_id, ipv6_subnet_id,
418 host->setNegative(true);
419 // Don't replace any existing value.
420 // nor matter if it fails.
421 cache_ptr_->insert(host, false);
422 }
423}
424
425} // end of isc::dhcp namespace
426} // end of isc namespace
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
static void add(HostDataSourceList &sources, const std::string &dbaccess)
Create and add an instance of a host data source.
static bool del(HostDataSourceList &sources, const std::string &db_type)
Delete a host data source.
Host Manager.
Definition: host_mgr.h:54
virtual void add(const HostPtr &host)
Adds a new host to the alternate data source.
Definition: host_mgr.cc:331
static void delAllBackends()
Delete all alternate backends.
Definition: host_mgr.cc:55
static void create()
Creates new instance of the HostMgr.
Definition: host_mgr.cc:40
bool negative_caching_
The negative caching flag.
Definition: host_mgr.h:340
virtual void cacheNegative(const SubnetID &ipv4_subnet_id, const SubnetID &ipv6_subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Cache a negative answer.
Definition: host_mgr.cc:408
virtual ConstHostCollection getAll(const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Return all hosts connected to any subnet for which reservations have been made using a specified iden...
Definition: host_mgr.cc:99
virtual ConstHostPtr get4Any(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns any host connected to the IPv4 subnet.
Definition: host_mgr.cc:125
virtual void cache(ConstHostPtr host) const
Cache an answer.
Definition: host_mgr.cc:395
virtual bool del6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len)
Attempts to delete a host by (subnet6-id, identifier, identifier-type)
Definition: host_mgr.cc:378
static bool delBackend(const std::string &db_type)
Delete an alternate host backend (aka host data source).
Definition: host_mgr.cc:50
static void addBackend(const std::string &access)
Add an alternate host backend (aka host data source).
Definition: host_mgr.cc:45
virtual ConstHostPtr get6(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv6 subnet.
Definition: host_mgr.cc:289
virtual ConstHostPtr get4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns a host connected to the IPv4 subnet.
Definition: host_mgr.cc:175
HostDataSourcePtr getHostDataSource() const
Returns the first host data source.
Definition: host_mgr.cc:60
static bool checkCacheBackend(bool logging=false)
Check for the cache host backend.
Definition: host_mgr.cc:68
virtual bool del(const SubnetID &subnet_id, const asiolink::IOAddress &addr)
Attempts to delete a host by address.
Definition: host_mgr.cc:346
static HostMgr & instance()
Returns a sole instance of the HostMgr.
Definition: host_mgr.cc:90
virtual ConstHostPtr get6Any(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len) const
Returns any host connected to the IPv6 subnet.
Definition: host_mgr.cc:242
virtual ConstHostCollection getAll4(const asiolink::IOAddress &address) const
Returns a collection of hosts using the specified IPv4 address.
Definition: host_mgr.cc:115
virtual bool del4(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len)
Attempts to delete a host by (subnet4-id, identifier, identifier-type)
Definition: host_mgr.cc:361
Represents a device with IPv4 and/or IPv6 reservations.
Definition: host.h:242
IdentifierType
Type of the host identifier.
Definition: host.h:252
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
Definition: host.cc:239
No host data source instance exception.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
boost::shared_ptr< BaseHostDataSource > HostDataSourcePtr
HostDataSource pointer.
isc::log::Logger hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
Definition: hosts_log.h:51
boost::shared_ptr< const CfgHosts > ConstCfgHostsPtr
Const pointer.
Definition: cfg_hosts.h:485
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition: host.h:725
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Definition: host.h:731
std::vector< HostDataSourcePtr > HostDataSourceList
HostDataSource list.
const int HOSTS_DBG_TRACE
Logging levels for the host reservations management.
Definition: hosts_log.h:27
boost::shared_ptr< CacheHostDataSource > CacheHostDataSourcePtr
CacheHostDataSource pointer.
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition: host.h:728
const int HOSTS_DBG_RESULTS
Records the results of the lookups.
Definition: hosts_log.h:33
Defines the logger used by the top-level component of kea-dhcp-ddns.