Kea 2.5.5
cfg_subnets6.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2023 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 <dhcp/dhcp6.h>
12#include <dhcpsrv/dhcpsrv_log.h>
14#include <dhcpsrv/subnet_id.h>
15#include <stats/stats_mgr.h>
16#include <boost/foreach.hpp>
17#include <string.h>
18#include <sstream>
19
20using namespace isc::asiolink;
21using namespace isc::data;
22
23using namespace std;
24
25namespace isc {
26namespace dhcp {
27
28void
30 if (getBySubnetId(subnet->getID())) {
31 isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv6 subnet '"
32 << subnet->getID() << "' is already in use");
33
34 } else if (getByPrefix(subnet->toText())) {
37 isc_throw(isc::dhcp::DuplicateSubnetID, "subnet with the prefix of '"
38 << subnet->toText() << "' already exists");
39 }
40
42 .arg(subnet->toText());
43 static_cast<void>(subnets_.insert(subnet));
44}
45
48 // Get the subnet with the same ID.
49 const SubnetID& subnet_id = subnet->getID();
50 auto& index = subnets_.template get<SubnetSubnetIdIndexTag>();
51 auto subnet_it = index.find(subnet_id);
52 if (subnet_it == index.end()) {
53 isc_throw(BadValue, "There is no IPv6 subnet with ID " << subnet_id);
54 }
55 Subnet6Ptr old = *subnet_it;
56 bool ret = index.replace(subnet_it, subnet);
57
59 .arg(subnet_id).arg(ret);
60 if (ret) {
61 return (old);
62 } else {
63 return (Subnet6Ptr());
64 }
65}
66
67void
69 del(subnet->getID());
70}
71
72void
73CfgSubnets6::del(const SubnetID& subnet_id) {
74 auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
75 auto subnet_it = index.find(subnet_id);
76 if (subnet_it == index.end()) {
77 isc_throw(BadValue, "no subnet with ID of '" << subnet_id
78 << "' found");
79 }
80
81 Subnet6Ptr subnet = *subnet_it;
82
83 index.erase(subnet_it);
84
86 .arg(subnet->toText());
87}
88
89void
91 CfgSubnets6& other) {
92 auto& index_id = subnets_.get<SubnetSubnetIdIndexTag>();
93 auto& index_prefix = subnets_.get<SubnetPrefixIndexTag>();
94
95 // Iterate over the subnets to be merged. They will replace the existing
96 // subnets with the same id. All new subnets will be inserted into the
97 // configuration into which we're merging.
98 auto const& other_subnets = other.getAll();
99 for (auto const& other_subnet : *other_subnets) {
100
101 // Check if there is a subnet with the same ID.
102 auto subnet_it = index_id.find(other_subnet->getID());
103 if (subnet_it != index_id.end()) {
104
105 // Subnet found.
106 auto existing_subnet = *subnet_it;
107
108 // If the existing subnet and other subnet
109 // are the same instance skip it.
110 if (existing_subnet == other_subnet) {
111 continue;
112 }
113
114 // We're going to replace the existing subnet with the other
115 // version. If it belongs to a shared network, we need
116 // remove it from that network.
117 SharedNetwork6Ptr network;
118 existing_subnet->getSharedNetwork(network);
119 if (network) {
120 network->del(existing_subnet->getID());
121 }
122
123 // Now we remove the existing subnet.
124 index_id.erase(subnet_it);
125 }
126
127 // Check if there is a subnet with the same prefix.
128 auto subnet_prefix_it = index_prefix.find(other_subnet->toText());
129 if (subnet_prefix_it != index_prefix.end()) {
130
131 // Subnet found.
132 auto existing_subnet = *subnet_prefix_it;
133
134 // Updating the id can lead to problems... e.g. reservation
135 // for the previous subnet ID.
136 // @todo: check reservations
137
138 // We're going to replace the existing subnet with the other
139 // version. If it belongs to a shared network, we need
140 // remove it from that network.
141 SharedNetwork6Ptr network;
142 existing_subnet->getSharedNetwork(network);
143 if (network) {
144 network->del(existing_subnet->getID());
145 }
146
147 // Now we remove the existing subnet.
148 index_prefix.erase(subnet_prefix_it);
149 }
150
151 // Create the subnet's options based on the given definitions.
152 other_subnet->getCfgOption()->createOptions(cfg_def);
153
154 // Create the options for pool based on the given definitions.
155 for (const auto& pool : other_subnet->getPoolsWritable(Lease::TYPE_NA)) {
156 pool->getCfgOption()->createOptions(cfg_def);
157 }
158
159 // Create the options for pd pool based on the given definitions.
160 for (const auto& pool : other_subnet->getPoolsWritable(Lease::TYPE_PD)) {
161 pool->getCfgOption()->createOptions(cfg_def);
162 }
163
164 // Add the "other" subnet to the our collection of subnets.
165 static_cast<void>(subnets_.insert(other_subnet));
166
167 // If it belongs to a shared network, find the network and
168 // add the subnet to it
169 std::string network_name = other_subnet->getSharedNetworkName();
170 if (!network_name.empty()) {
171 SharedNetwork6Ptr network = networks->getByName(network_name);
172 if (network) {
173 network->add(other_subnet);
174 } else {
175 // This implies the shared-network collection we were given
176 // is out of sync with the subnets we were given.
177 isc_throw(InvalidOperation, "Cannot assign subnet ID of "
178 << other_subnet->getID()
179 << " to shared network: " << network_name
180 << ", network does not exist");
181 }
182 }
183 // Instantiate the configured allocators and their states.
184 other_subnet->createAllocators();
185 }
186}
187
189CfgSubnets6::getBySubnetId(const SubnetID& subnet_id) const {
190 const auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
191 auto subnet_it = index.find(subnet_id);
192 return ((subnet_it != index.cend()) ? (*subnet_it) : ConstSubnet6Ptr());
193}
194
196CfgSubnets6::getByPrefix(const std::string& subnet_text) const {
197 const auto& index = subnets_.get<SubnetPrefixIndexTag>();
198 auto subnet_it = index.find(subnet_text);
199 return ((subnet_it != index.cend()) ? (*subnet_it) : ConstSubnet6Ptr());
200}
201
204 // Initialize subnet selector with the values used to select the subnet.
205 SubnetSelector selector;
206 selector.iface_name_ = query->getIface();
207 selector.remote_address_ = query->getRemoteAddr();
208 selector.first_relay_linkaddr_ = IOAddress("::");
209 selector.client_classes_ = query->classes_;
210
211 // Initialize fields specific to relayed messages.
212 if (!query->relay_info_.empty()) {
213 BOOST_REVERSE_FOREACH(Pkt6::RelayInfo relay, query->relay_info_) {
214 if (!relay.linkaddr_.isV6Zero() &&
215 !relay.linkaddr_.isV6LinkLocal()) {
216 selector.first_relay_linkaddr_ = relay.linkaddr_;
217 break;
218 }
219 }
220 selector.interface_id_ =
221 query->getAnyRelayOption(D6O_INTERFACE_ID,
223 }
224
225 return (selector);
226}
227
230 Subnet6Ptr subnet;
231
232 // If relay agent link address is set to zero it means that we're dealing
233 // with a directly connected client.
234 if (selector.first_relay_linkaddr_ == IOAddress("::")) {
235 // If interface name is known try to match it with interface names
236 // specified for configured subnets.
237 if (!selector.iface_name_.empty()) {
238 subnet = selectSubnet(selector.iface_name_,
239 selector.client_classes_);
240 }
241
242 // If interface name didn't match, try the client's address.
243 if (!subnet && selector.remote_address_ != IOAddress("::")) {
244 subnet = selectSubnet(selector.remote_address_,
245 selector.client_classes_);
246 }
247
248 // If relay agent link address is set, we're dealing with a relayed message.
249 } else {
250 // Find the subnet using the Interface Id option, if present.
251 subnet = selectSubnet(selector.interface_id_, selector.client_classes_);
252
253 // If Interface ID option could not be matched for any subnet, try
254 // the relay agent link address.
255 if (!subnet) {
256 subnet = selectSubnet(selector.first_relay_linkaddr_,
257 selector.client_classes_,
258 true);
259 }
260 }
261
262 // Return subnet found, or NULL if not found.
263 return (subnet);
264}
265
268 const ClientClasses& client_classes,
269 const bool is_relay_address) const {
270 // If the specified address is a relay address we first need to match
271 // it with the relay addresses specified for all subnets.
272 if (is_relay_address) {
273 for (auto const& subnet : subnets_) {
274
275 // If the specified address matches a relay address, return this
276 // subnet.
277 if (subnet->hasRelays()) {
278 if (!subnet->hasRelayAddress(address)) {
279 continue;
280 }
281
282 } else {
283 SharedNetwork6Ptr network;
284 subnet->getSharedNetwork(network);
285 if (!network || !network->hasRelayAddress(address)) {
286 continue;
287 }
288 }
289
290 if (subnet->clientSupported(client_classes)) {
291 // The relay address is matching the one specified for a subnet
292 // or its shared network.
295 .arg(subnet->toText()).arg(address.toText());
296 return (subnet);
297 }
298 }
299 }
300
301 // No success so far. Check if the specified address is in range
302 // with any subnet.
303 for (auto const& subnet : subnets_) {
304 if (subnet->inRange(address) && subnet->clientSupported(client_classes)) {
306 .arg(subnet->toText()).arg(address.toText());
307 return (subnet);
308 }
309 }
310
313 .arg(address.toText());
314
315 // Nothing found.
316 return (Subnet6Ptr());
317}
318
320CfgSubnets6::selectSubnet(const std::string& iface_name,
321 const ClientClasses& client_classes) const {
322 // If empty interface specified, we can't select subnet by interface.
323 if (!iface_name.empty()) {
324 for (auto const& subnet : subnets_) {
325
326 // If interface name matches with the one specified for the subnet
327 // and the client is not rejected based on the classification,
328 // return the subnet.
329 if ((subnet->getIface() == iface_name) &&
330 subnet->clientSupported(client_classes)) {
333 .arg(subnet->toText()).arg(iface_name);
334 return (subnet);
335 }
336 }
337 }
338
341 .arg(iface_name);
342
343 // No subnet found for this interface name.
344 return (Subnet6Ptr());
345}
346
348CfgSubnets6::selectSubnet(const OptionPtr& interface_id,
349 const ClientClasses& client_classes) const {
350 // We can only select subnet using an interface id, if the interface
351 // id is known.
352 if (interface_id) {
353 for (auto const& subnet : subnets_) {
354
355 // If interface id matches for the subnet and the subnet is not
356 // rejected based on the classification.
357 if (subnet->getInterfaceId() &&
358 subnet->getInterfaceId()->equals(interface_id) &&
359 subnet->clientSupported(client_classes)) {
360
363 .arg(subnet->toText());
364 return (subnet);
365 }
366 }
367
370 .arg(interface_id->toText());
371 }
372
373 // No subnet found.
374 return (Subnet6Ptr());
375}
376
381 for (auto const& subnet : subnets_) {
382 if (subnet->getID() == id) {
383 return (subnet);
384 }
385 }
386 return (Subnet6Ptr());
387}
388
390CfgSubnets6::getLinks(const IOAddress& link_addr, uint8_t& link_len) const {
391 SubnetIDSet links;
392 bool link_len_set = false;
393 for (auto const& subnet : subnets_) {
394 if (!subnet->inRange(link_addr)) {
395 continue;
396 }
397 uint8_t plen = subnet->get().second;
398 if (!link_len_set || (plen < link_len)) {
399 link_len_set = true;
400 link_len = plen;
401 }
402 links.insert(subnet->getID());
403 }
404 return (links);
405}
406
407void
409 using namespace isc::stats;
410
411 StatsMgr& stats_mgr = StatsMgr::instance();
412 // For each v6 subnet currently configured, remove the statistics.
413 for (auto const& subnet6 : subnets_) {
414 SubnetID subnet_id = subnet6->getID();
415 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
416 "total-nas"));
417
418 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
419 "assigned-nas"));
420
421 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
422 "cumulative-assigned-nas"));
423
424 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
425 "total-pds"));
426
427 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
428 "assigned-pds"));
429
430 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
431 "cumulative-assigned-pds"));
432
433 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
434 "declined-addresses"));
435
436 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
437 "reclaimed-declined-addresses"));
438
439 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
440 "reclaimed-leases"));
441
442 for (const auto& pool : subnet6->getPools(Lease::TYPE_NA)) {
443 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
444 StatsMgr::generateName("pool", pool->getID(),
445 "total-nas")));
446
447 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
448 StatsMgr::generateName("pool", pool->getID(),
449 "assigned-nas")));
450
451 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
452 StatsMgr::generateName("pool", pool->getID(),
453 "cumulative-assigned-nas")));
454
455 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
456 StatsMgr::generateName("pool", pool->getID(),
457 "declined-addresses")));
458
459 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
460 StatsMgr::generateName("pool", pool->getID(),
461 "reclaimed-declined-addresses")));
462
463 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
464 StatsMgr::generateName("pool", pool->getID(),
465 "reclaimed-leases")));
466 }
467
468 for (const auto& pool : subnet6->getPools(Lease::TYPE_PD)) {
469 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
470 StatsMgr::generateName("pd-pool", pool->getID(),
471 "total-pds")));
472
473 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
474 StatsMgr::generateName("pd-pool", pool->getID(),
475 "assigned-pds")));
476
477 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
478 StatsMgr::generateName("pd-pool", pool->getID(),
479 "cumulative-assigned-pds")));
480
481 stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
482 StatsMgr::generateName("pd-pool", pool->getID(),
483 "reclaimed-leases")));
484 }
485 }
486}
487
488void
490 using namespace isc::stats;
491
492 StatsMgr& stats_mgr = StatsMgr::instance();
493 // For each v6 subnet currently configured, calculate totals
494 for (auto const& subnet6 : subnets_) {
495 SubnetID subnet_id = subnet6->getID();
496
497 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
498 "total-nas"),
499 subnet6->getPoolCapacity(Lease::TYPE_NA));
500
501 stats_mgr.setValue(StatsMgr::generateName("subnet", subnet_id,
502 "total-pds"),
503 subnet6->getPoolCapacity(Lease::TYPE_PD));
504
505 const std::string& name_nas(StatsMgr::generateName("subnet", subnet_id,
506 "cumulative-assigned-nas"));
507 if (!stats_mgr.getObservation(name_nas)) {
508 stats_mgr.setValue(name_nas, static_cast<int64_t>(0));
509 }
510
511 const std::string& name_pds(StatsMgr::generateName("subnet", subnet_id,
512 "cumulative-assigned-pds"));
513 if (!stats_mgr.getObservation(name_pds)) {
514 stats_mgr.setValue(name_pds, static_cast<int64_t>(0));
515 }
516
517 string const& name_ia_na_reuses(StatsMgr::generateName("subnet", subnet_id,
518 "v6-ia-na-lease-reuses"));
519 if (!stats_mgr.getObservation(name_ia_na_reuses)) {
520 stats_mgr.setValue(name_ia_na_reuses, int64_t(0));
521 }
522
523 string const& name_ia_pd_reuses(StatsMgr::generateName("subnet", subnet_id,
524 "v6-ia-pd-lease-reuses"));
525 if (!stats_mgr.getObservation(name_ia_pd_reuses)) {
526 stats_mgr.setValue(name_ia_pd_reuses, int64_t(0));
527 }
528
529 for (const auto& pool : subnet6->getPools(Lease::TYPE_NA)) {
530 const std::string& name_total_nas(StatsMgr::generateName("subnet", subnet_id,
531 StatsMgr::generateName("pool", pool->getID(),
532 "total-nas")));
533 if (!stats_mgr.getObservation(name_total_nas)) {
534 stats_mgr.setValue(name_total_nas, pool->getCapacity());
535 } else {
536 stats_mgr.addValue(name_total_nas, pool->getCapacity());
537 }
538
539 const std::string& name_ca_nas(StatsMgr::generateName("subnet", subnet_id,
540 StatsMgr::generateName("pool", pool->getID(),
541 "cumulative-assigned-nas")));
542 if (!stats_mgr.getObservation(name_ca_nas)) {
543 stats_mgr.setValue(name_ca_nas, static_cast<int64_t>(0));
544 }
545 }
546
547 for (const auto& pool : subnet6->getPools(Lease::TYPE_PD)) {
548 const std::string& name_total_pds(StatsMgr::generateName("subnet", subnet_id,
549 StatsMgr::generateName("pd-pool", pool->getID(),
550 "total-pds")));
551 if (!stats_mgr.getObservation(name_total_pds)) {
552 stats_mgr.setValue(name_total_pds, pool->getCapacity());
553 } else {
554 stats_mgr.addValue(name_total_pds, pool->getCapacity());
555 }
556
557 const std::string& name_ca_pds(StatsMgr::generateName("subnet", subnet_id,
558 StatsMgr::generateName("pd-pool", pool->getID(),
559 "cumulative-assigned-pds")));
560 if (!stats_mgr.getObservation(name_ca_pds)) {
561 stats_mgr.setValue(name_ca_pds, static_cast<int64_t>(0));
562 }
563 }
564 }
565
566 // Only recount the stats if we have subnets.
567 if (subnets_.begin() != subnets_.end()) {
569 }
570}
571
572void
574 for (auto subnet : subnets_) {
575 subnet->initAllocatorsAfterConfigure();
576 }
577}
578
579void
581 subnets_.clear();
582}
583
587 // Iterate subnets
588 for (auto const& subnet : subnets_) {
589 result->add(subnet->toElement());
590 }
591 return (result);
592}
593
594} // end of namespace isc::dhcp
595} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a function is called in a prohibited way.
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:299
Holds subnets configured for the DHCPv6 server.
Definition: cfg_subnets6.h:34
SubnetIDSet getLinks(const asiolink::IOAddress &link_addr, uint8_t &link_len) const
Convert a link address into a link set.
void updateStatistics()
Updates statistics.
Subnet6Ptr replace(const Subnet6Ptr &subnet)
Replaces subnet in the configuration.
Definition: cfg_subnets6.cc:47
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
void merge(CfgOptionDefPtr cfg_def, CfgSharedNetworks6Ptr networks, CfgSubnets6 &other)
Merges specified subnet configuration into this configuration.
Definition: cfg_subnets6.cc:90
Subnet6Ptr selectSubnet(const SubnetSelector &selector) const
Selects a subnet using parameters specified in the selector.
Subnet6Ptr getSubnet(const SubnetID id) const
Returns subnet with specified subnet-id value.
void removeStatistics()
Removes statistics.
const Subnet6Collection * getAll() const
Returns pointer to the collection of all IPv6 subnets.
Definition: cfg_subnets6.h:120
void add(const Subnet6Ptr &subnet)
Adds new subnet to the configuration.
Definition: cfg_subnets6.cc:29
void clear()
Clears all subnets from the configuration.
static SubnetSelector initSelector(const Pkt6Ptr &query)
Build selector from a client's message.
void del(const ConstSubnet6Ptr &subnet)
Removes subnet from the configuration.
Definition: cfg_subnets6.cc:68
ConstSubnet6Ptr getByPrefix(const std::string &subnet_prefix) const
Returns const pointer to a subnet which matches the specified prefix in the canonical form.
void initAllocatorsAfterConfigure()
Calls initAllocatorsAfterConfigure for each subnet.
ConstSubnet6Ptr getBySubnetId(const SubnetID &subnet_id) const
Returns const pointer to a subnet identified by the specified subnet identifier.
Container for storing client class names.
Definition: classify.h:108
Exception thrown upon attempt to add subnet with an ID that belongs to the subnet that already exists...
Definition: subnet_id.h:36
static TrackingLeaseMgr & instance()
Return current lease manager.
void recountLeaseStats6()
Recalculates per-subnet and global stats for IPv6 leases.
Definition: lease_mgr.cc:285
@ RELAY_GET_FIRST
Definition: pkt6.h:77
Statistics Manager class.
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
@ D6O_INTERFACE_ID
Definition: dhcp6.h:38
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
bool del(const std::string &name)
Removes specified statistic.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
boost::shared_ptr< Element > ElementPtr
Definition: data.h:28
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET6_IFACE
const isc::log::MessageID DHCPSRV_CFGMGR_ADD_SUBNET6
std::set< dhcp::SubnetID > SubnetIDSet
Ordered list aka set of subnetIDs.
Definition: subnet_id.h:43
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET6_RELAY
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition: subnet.h:660
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
const isc::log::MessageID DHCPSRV_CFGMGR_UPDATE_SUBNET6
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition: subnet.h:663
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
boost::shared_ptr< CfgSharedNetworks6 > CfgSharedNetworks6Ptr
Pointer to the configuration of IPv6 shared networks.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET6
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET6_IFACE_ID
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition: pkt6.h:31
const isc::log::MessageID DHCPSRV_CFGMGR_DEL_SUBNET6
const isc::log::MessageID DHCPSRV_SUBNET6_SELECT_BY_INTERFACE_ID_NO_MATCH
const isc::log::MessageID DHCPSRV_SUBNET6_SELECT_BY_ADDRESS_NO_MATCH
const isc::log::MessageID DHCPSRV_SUBNET6_SELECT_BY_INTERFACE_NO_MATCH
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
Defines the logger used by the top-level component of kea-lfc.
@ TYPE_PD
the lease contains IPv6 prefix (for prefix delegation)
Definition: lease.h:49
@ TYPE_NA
the lease contains non-temporary IPv6 address
Definition: lease.h:47
structure that describes a single relay information
Definition: pkt6.h:85
isc::asiolink::IOAddress linkaddr_
fixed field in relay-forw/relay-reply
Definition: pkt6.h:96
Tag for the index for searching by subnet prefix.
Definition: subnet.h:817
Subnet selector used to specify parameters used to select a subnet.
std::string iface_name_
Name of the interface on which the message was received.
ClientClasses client_classes_
Classes that the client belongs to.
asiolink::IOAddress remote_address_
Source address of the message.
OptionPtr interface_id_
Interface id option.
asiolink::IOAddress first_relay_linkaddr_
First relay link address.
Tag for the index for searching by subnet identifier.
Definition: subnet.h:814