Kea  2.5.3
cfg_subnets4.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/iface_mgr.h>
9 #include <dhcp/option_custom.h>
10 #include <dhcpsrv/cfgmgr.h>
11 #include <dhcpsrv/cfg_subnets4.h>
12 #include <dhcpsrv/dhcpsrv_log.h>
14 #include <dhcpsrv/shared_network.h>
15 #include <dhcpsrv/subnet_id.h>
16 #include <asiolink/io_address.h>
18 #include <stats/stats_mgr.h>
19 #include <sstream>
20 
21 using namespace isc::asiolink;
22 using namespace isc::data;
23 
24 namespace isc {
25 namespace dhcp {
26 
27 void
28 CfgSubnets4::add(const Subnet4Ptr& subnet) {
29  if (getBySubnetId(subnet->getID())) {
30  isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv4 subnet '"
31  << subnet->getID() << "' is already in use");
32 
33  } else if (getByPrefix(subnet->toText())) {
36  isc_throw(isc::dhcp::DuplicateSubnetID, "subnet with the prefix of '"
37  << subnet->toText() << "' already exists");
38  }
39 
41  .arg(subnet->toText());
42  static_cast<void>(subnets_.insert(subnet));
43 }
44 
46 CfgSubnets4::replace(const Subnet4Ptr& subnet) {
47  // Get the subnet with the same ID.
48  const SubnetID& subnet_id = subnet->getID();
49  auto& index = subnets_.template get<SubnetSubnetIdIndexTag>();
50  auto subnet_it = index.find(subnet_id);
51  if (subnet_it == index.end()) {
52  isc_throw(BadValue, "There is no IPv4 subnet with ID " <<subnet_id);
53  }
54  Subnet4Ptr old = *subnet_it;
55  bool ret = index.replace(subnet_it, subnet);
56 
58  .arg(subnet_id).arg(ret);
59  if (ret) {
60  return (old);
61  } else {
62  return (Subnet4Ptr());
63  }
64 }
65 
66 void
67 CfgSubnets4::del(const ConstSubnet4Ptr& subnet) {
68  del(subnet->getID());
69 }
70 
71 void
72 CfgSubnets4::del(const SubnetID& subnet_id) {
73  auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
74  auto subnet_it = index.find(subnet_id);
75  if (subnet_it == index.end()) {
76  isc_throw(BadValue, "no subnet with ID of '" << subnet_id
77  << "' found");
78  }
79 
80  Subnet4Ptr subnet = *subnet_it;
81 
82  index.erase(subnet_it);
83 
85  .arg(subnet->toText());
86 }
87 
88 void
90  CfgSubnets4& other) {
91  auto& index_id = subnets_.get<SubnetSubnetIdIndexTag>();
92  auto& index_prefix = subnets_.get<SubnetPrefixIndexTag>();
93 
94  // Iterate over the subnets to be merged. They will replace the existing
95  // subnets with the same id. All new subnets will be inserted into the
96  // configuration into which we're merging.
97  auto const& other_subnets = other.getAll();
98  for (auto const& other_subnet : (*other_subnets)) {
99 
100  // Check if there is a subnet with the same ID.
101  auto subnet_id_it = index_id.find(other_subnet->getID());
102  if (subnet_id_it != index_id.end()) {
103 
104  // Subnet found.
105  auto existing_subnet = *subnet_id_it;
106 
107  // If the existing subnet and other subnet
108  // are the same instance skip it.
109  if (existing_subnet == other_subnet) {
110  continue;
111  }
112 
113  // Updating the prefix can lead to problems... e.g. pools
114  // and reservations going outside range.
115  // @todo: check prefix change.
116 
117  // We're going to replace the existing subnet with the other
118  // version. If it belongs to a shared network, we need
119  // remove it from that network.
120  SharedNetwork4Ptr network;
121  existing_subnet->getSharedNetwork(network);
122  if (network) {
123  network->del(existing_subnet->getID());
124  }
125 
126  // Now we remove the existing subnet.
127  index_id.erase(subnet_id_it);
128  }
129 
130  // Check if there is a subnet with the same prefix.
131  auto subnet_prefix_it = index_prefix.find(other_subnet->toText());
132  if (subnet_prefix_it != index_prefix.end()) {
133 
134  // Subnet found.
135  auto existing_subnet = *subnet_prefix_it;
136 
137  // Updating the id can lead to problems... e.g. reservation
138  // for the previous subnet ID.
139  // @todo: check reservations
140 
141  // We're going to replace the existing subnet with the other
142  // version. If it belongs to a shared network, we need
143  // remove it from that network.
144  SharedNetwork4Ptr network;
145  existing_subnet->getSharedNetwork(network);
146  if (network) {
147  network->del(existing_subnet->getID());
148  }
149 
150  // Now we remove the existing subnet.
151  index_prefix.erase(subnet_prefix_it);
152  }
153 
154  // Create the subnet's options based on the given definitions.
155  other_subnet->getCfgOption()->createOptions(cfg_def);
156 
157  // Create the options for pool based on the given definitions.
158  for (const auto& pool : other_subnet->getPoolsWritable(Lease::TYPE_V4)) {
159  pool->getCfgOption()->createOptions(cfg_def);
160  }
161 
162  // Add the "other" subnet to the our collection of subnets.
163  static_cast<void>(subnets_.insert(other_subnet));
164 
165  // If it belongs to a shared network, find the network and
166  // add the subnet to it
167  std::string network_name = other_subnet->getSharedNetworkName();
168  if (!network_name.empty()) {
169  SharedNetwork4Ptr network = networks->getByName(network_name);
170  if (network) {
171  network->add(other_subnet);
172  } else {
173  // This implies the shared-network collection we were given
174  // is out of sync with the subnets we were given.
175  isc_throw(InvalidOperation, "Cannot assign subnet ID of "
176  << other_subnet->getID()
177  << " to shared network: " << network_name
178  << ", network does not exist");
179  }
180  }
181  // Instantiate the configured allocator and its state.
182  other_subnet->createAllocators();
183  }
184 }
185 
187 CfgSubnets4::getBySubnetId(const SubnetID& subnet_id) const {
188  const auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
189  auto subnet_it = index.find(subnet_id);
190  return ((subnet_it != index.cend()) ? (*subnet_it) : ConstSubnet4Ptr());
191 }
192 
194 CfgSubnets4::getByPrefix(const std::string& subnet_text) const {
195  const auto& index = subnets_.get<SubnetPrefixIndexTag>();
196  auto subnet_it = index.find(subnet_text);
197  return ((subnet_it != index.cend()) ? (*subnet_it) : ConstSubnet4Ptr());
198 }
199 
200 bool
201 CfgSubnets4::hasSubnetWithServerId(const asiolink::IOAddress& server_id) const {
202  const auto& index = subnets_.get<SubnetServerIdIndexTag>();
203  auto subnet_it = index.find(server_id);
204  return (subnet_it != index.cend());
205 }
206 
208 CfgSubnets4::initSelector(const Pkt4Ptr& query) {
209  SubnetSelector selector;
210  selector.ciaddr_ = query->getCiaddr();
211  selector.giaddr_ = query->getGiaddr();
212  selector.local_address_ = query->getLocalAddr();
213  selector.remote_address_ = query->getRemoteAddr();
214  selector.client_classes_ = query->classes_;
215  selector.iface_name_ = query->getIface();
216 
217  // If the link-selection sub-option is present, extract its value.
218  // "The link-selection sub-option is used by any DHCP relay agent
219  // that desires to specify a subnet/link for a DHCP client request
220  // that it is relaying but needs the subnet/link specification to
221  // be different from the IP address the DHCP server should use
222  // when communicating with the relay agent." (RFC 3527)
223  //
224  // Try first Relay Agent Link Selection sub-option
225  OptionPtr rai = query->getOption(DHO_DHCP_AGENT_OPTIONS);
226  if (rai) {
227  OptionCustomPtr rai_custom =
228  boost::dynamic_pointer_cast<OptionCustom>(rai);
229  if (rai_custom) {
230  // If Relay Agent Information Link Selection is ignored in the
231  // configuration, skip returning the related subnet selector here,
232  // and move on to normal subnet selection.
233  bool ignore_link_sel = CfgMgr::instance().getCurrentCfg()->
234  getIgnoreRAILinkSelection();
235  if (!ignore_link_sel) {
236  OptionPtr link_select =
237  rai_custom->getOption(RAI_OPTION_LINK_SELECTION);
238  if (link_select) {
239  OptionBuffer link_select_buf = link_select->getData();
240  if (link_select_buf.size() == sizeof(uint32_t)) {
241  selector.option_select_ =
242  IOAddress::fromBytes(AF_INET, &link_select_buf[0]);
243  return (selector);
244  }
245  }
246  }
247  }
248  }
249  // The query does not include a RAI option or that option does
250  // not contain the link-selection sub-option. Try subnet-selection
251  // option.
252  OptionPtr sbnsel = query->getOption(DHO_SUBNET_SELECTION);
253  if (sbnsel) {
254  OptionCustomPtr oc =
255  boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
256  if (oc) {
257  selector.option_select_ = oc->readAddress();
258  }
259  }
260  return (selector);
261 }
262 
264 CfgSubnets4::selectSubnet4o6(const SubnetSelector& selector) const {
265  for (auto const& subnet : subnets_) {
266  Cfg4o6& cfg4o6 = subnet->get4o6();
267 
268  // Is this an 4o6 subnet at all?
269  if (!cfg4o6.enabled()) {
270  continue; // No? Let's try the next one.
271  }
272 
273  // First match criteria: check if we have a prefix/len defined.
274  std::pair<asiolink::IOAddress, uint8_t> pref = cfg4o6.getSubnet4o6();
275  if (!pref.first.isV6Zero()) {
276 
277  // Let's check if the IPv6 address is in range
278  IOAddress first = firstAddrInPrefix(pref.first, pref.second);
279  IOAddress last = lastAddrInPrefix(pref.first, pref.second);
280  if ((first <= selector.remote_address_) &&
281  (selector.remote_address_ <= last)) {
282  return (subnet);
283  }
284  }
285 
286  // Second match criteria: check if the interface-id matches
287  if (cfg4o6.getInterfaceId() && selector.interface_id_ &&
288  cfg4o6.getInterfaceId()->equals(selector.interface_id_)) {
289  return (subnet);
290  }
291 
292  // Third match criteria: check if the interface name matches
293  if (!cfg4o6.getIface4o6().empty() && !selector.iface_name_.empty()
294  && cfg4o6.getIface4o6() == selector.iface_name_) {
295  return (subnet);
296  }
297  }
298 
300 
301  // Ok, wasn't able to find any matching subnet.
302  return (Subnet4Ptr());
303 }
304 
306 CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
307  // First use RAI link select sub-option or subnet select option
308  if (!selector.option_select_.isV4Zero()) {
309  return (selectSubnet(selector.option_select_,
310  selector.client_classes_));
311  } else {
314  }
315 
316  // If relayed message has been received, try to match the giaddr with the
317  // relay address specified for a subnet and/or shared network. It is also
318  // possible that the relay address will not match with any of the relay
319  // addresses across all subnets, but we need to verify that for all subnets
320  // before we can try to use the giaddr to match with the subnet prefix.
321  if (!selector.giaddr_.isV4Zero()) {
322  for (auto const& subnet : subnets_) {
323 
324  // If relay information is specified for this subnet, it must match.
325  // Otherwise, we ignore this subnet.
326  if (subnet->hasRelays()) {
327  if (!subnet->hasRelayAddress(selector.giaddr_)) {
328  continue;
329  }
330  } else {
331  // Relay information is not specified on the subnet level,
332  // so let's try matching on the shared network level.
333  SharedNetwork4Ptr network;
334  subnet->getSharedNetwork(network);
335  if (!network || !(network->hasRelayAddress(selector.giaddr_))) {
336  continue;
337  }
338  }
339 
340  // If a subnet meets the client class criteria return it.
341  if (subnet->clientSupported(selector.client_classes_)) {
344  .arg(subnet->toText())
345  .arg(selector.giaddr_.toText());
346  return (subnet);
347  }
348  }
351  .arg(selector.giaddr_.toText());
352  } else {
355  }
356 
357  // If we got to this point it means that we were not able to match the
358  // giaddr with any of the addresses specified for subnets. Let's determine
359  // what address from the client's packet to use to match with the
360  // subnets' prefixes.
361 
363  // If there is a giaddr, use it for subnet selection.
364  if (!selector.giaddr_.isV4Zero()) {
365  address = selector.giaddr_;
366 
367  // If it is a Renew or Rebind, use the ciaddr.
368  } else if (!selector.ciaddr_.isV4Zero() &&
369  !selector.local_address_.isV4Bcast()) {
370  address = selector.ciaddr_;
371 
372  // If ciaddr is not specified, use the source address.
373  } else if (!selector.remote_address_.isV4Zero() &&
374  !selector.local_address_.isV4Bcast()) {
375  address = selector.remote_address_;
376 
377  // If local interface name is known, use the local address on this
378  // interface.
379  } else if (!selector.iface_name_.empty()) {
380  IfacePtr iface = IfaceMgr::instance().getIface(selector.iface_name_);
381  // This should never happen in the real life. Hence we throw an
382  // exception.
383  if (iface == NULL) {
384  isc_throw(isc::BadValue, "interface " << selector.iface_name_
385  << " doesn't exist and therefore it is impossible"
386  " to find a suitable subnet for its IPv4 address");
387  }
388 
389  // Attempt to select subnet based on the interface name.
390  Subnet4Ptr subnet = selectSubnet(selector.iface_name_,
391  selector.client_classes_);
392 
393  // If it matches - great. If not, we'll try to use a different
394  // selection criteria below.
395  if (subnet) {
396  return (subnet);
397  } else {
398  // Let's try to get an address from the local interface and
399  // try to match it to defined subnet.
400  iface->getAddress4(address);
401  }
402  }
403 
404  // Unable to find a suitable address to use for subnet selection.
405  if (address.isV4Zero()) {
408 
409  return (Subnet4Ptr());
410  }
411 
412  // We have identified an address in the client's packet that can be
413  // used for subnet selection. Match this packet with the subnets.
414  return (selectSubnet(address, selector.client_classes_));
415 }
416 
418 CfgSubnets4::selectSubnet(const std::string& iface,
419  const ClientClasses& client_classes) const {
420  for (auto const& subnet : subnets_) {
421  Subnet4Ptr subnet_selected;
422 
423  // First, try subnet specific interface name.
424  if (!subnet->getIface(Network4::Inheritance::NONE).empty()) {
425  if (subnet->getIface(Network4::Inheritance::NONE) == iface) {
426  subnet_selected = subnet;
427  }
428 
429  } else {
430  // Interface not specified for a subnet, so let's try if
431  // we can match with shared network specific setting of
432  // the interface.
433  SharedNetwork4Ptr network;
434  subnet->getSharedNetwork(network);
435  if (network &&
436  (network->getIface(Network4::Inheritance::NONE) == iface)) {
437  subnet_selected = subnet;
438  }
439  }
440 
441  if (subnet_selected) {
442  // If a subnet meets the client class criteria return it.
443  if (subnet_selected->clientSupported(client_classes)) {
446  .arg(subnet->toText())
447  .arg(iface);
448  return (subnet_selected);
449  }
450  }
451  }
452 
455  .arg(iface);
456 
457  // Failed to find a subnet.
458  return (Subnet4Ptr());
459 }
460 
462 CfgSubnets4::getSubnet(const SubnetID id) const {
465  for (auto const& subnet : subnets_) {
466  if (subnet->getID() == id) {
467  return (subnet);
468  }
469  }
470  return (Subnet4Ptr());
471 }
472 
474 CfgSubnets4::selectSubnet(const IOAddress& address,
475  const ClientClasses& client_classes) const {
476  for (auto const& subnet : subnets_) {
477 
478  // Address is in range for the subnet prefix, so return it.
479  if (!subnet->inRange(address)) {
480  continue;
481  }
482 
483  // If a subnet meets the client class criteria return it.
484  if (subnet->clientSupported(client_classes)) {
486  .arg(subnet->toText())
487  .arg(address.toText());
488  return (subnet);
489  }
490  }
491 
494  .arg(address.toText());
495 
496  // Failed to find a subnet.
497  return (Subnet4Ptr());
498 }
499 
501 CfgSubnets4::getLinks(const IOAddress& link_addr, uint8_t& link_len) const {
502  SubnetIDSet links;
503  bool link_len_set = false;
504  for (auto const& subnet : subnets_) {
505  if (!subnet->inRange(link_addr)) {
506  continue;
507  }
508  uint8_t plen = subnet->get().second;
509  if (!link_len_set || (plen < link_len)) {
510  link_len_set = true;
511  link_len = plen;
512  }
513  links.insert(subnet->getID());
514  }
515  return (links);
516 }
517 
518 void
519 CfgSubnets4::removeStatistics() {
520  using namespace isc::stats;
521 
522  // For each v4 subnet currently configured, remove the statistic.
523  StatsMgr& stats_mgr = StatsMgr::instance();
524  for (auto const& subnet4 : subnets_) {
525  SubnetID subnet_id = subnet4->getID();
526  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
527  "total-addresses"));
528 
529  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
530  "assigned-addresses"));
531 
532  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
533  "cumulative-assigned-addresses"));
534 
535  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
536  "declined-addresses"));
537 
538  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
539  "reclaimed-declined-addresses"));
540 
541  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
542  "reclaimed-leases"));
543 
544  for (const auto& pool : subnet4->getPools(Lease::TYPE_V4)) {
545  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
546  StatsMgr::generateName("pool", pool->getID(),
547  "total-addresses")));
548 
549  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
550  StatsMgr::generateName("pool", pool->getID(),
551  "assigned-addresses")));
552 
553  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
554  StatsMgr::generateName("pool", pool->getID(),
555  "cumulative-assigned-addresses")));
556 
557  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
558  StatsMgr::generateName("pool", pool->getID(),
559  "declined-addresses")));
560 
561  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
562  StatsMgr::generateName("pool", pool->getID(),
563  "reclaimed-declined-addresses")));
564 
565  stats_mgr.del(StatsMgr::generateName("subnet", subnet_id,
566  StatsMgr::generateName("pool", pool->getID(),
567  "reclaimed-leases")));
568  }
569  }
570 }
571 
572 void
573 CfgSubnets4::updateStatistics() {
574  using namespace isc::stats;
575 
576  StatsMgr& stats_mgr = StatsMgr::instance();
577  for (auto const& subnet4 : subnets_) {
578  SubnetID subnet_id = subnet4->getID();
579 
580  stats_mgr.setValue(StatsMgr::
581  generateName("subnet", subnet_id, "total-addresses"),
582  int64_t(subnet4->getPoolCapacity(Lease::TYPE_V4)));
583  const std::string& name(StatsMgr::generateName("subnet", subnet_id,
584  "cumulative-assigned-addresses"));
585  if (!stats_mgr.getObservation(name)) {
586  stats_mgr.setValue(name, static_cast<int64_t>(0));
587  }
588 
589  const std::string& name_reuses(StatsMgr::generateName("subnet", subnet_id,
590  "v4-lease-reuses"));
591  if (!stats_mgr.getObservation(name_reuses)) {
592  stats_mgr.setValue(name_reuses, int64_t(0));
593  }
594 
595  const std::string& name_conflicts(StatsMgr::generateName("subnet", subnet_id,
596  "v4-reservation-conflicts"));
597  if (!stats_mgr.getObservation(name_conflicts)) {
598  stats_mgr.setValue(name_conflicts, static_cast<int64_t>(0));
599  }
600 
601  for (const auto& pool : subnet4->getPools(Lease::TYPE_V4)) {
602  const std::string& name_total(StatsMgr::generateName("subnet", subnet_id,
603  StatsMgr::generateName("pool", pool->getID(),
604  "total-addresses")));
605  if (!stats_mgr.getObservation(name_total)) {
606  stats_mgr.setValue(name_total, static_cast<int64_t>(pool->getCapacity()));
607  } else {
608  stats_mgr.addValue(name_total, static_cast<int64_t>(pool->getCapacity()));
609  }
610 
611  const std::string& name_ca(StatsMgr::generateName("subnet", subnet_id,
612  StatsMgr::generateName("pool", pool->getID(),
613  "cumulative-assigned-addresses")));
614  if (!stats_mgr.getObservation(name_ca)) {
615  stats_mgr.setValue(name_ca, static_cast<int64_t>(0));
616  }
617  }
618  }
619 
620  // Only recount the stats if we have subnets.
621  if (subnets_.begin() != subnets_.end()) {
622  LeaseMgrFactory::instance().recountLeaseStats4();
623  }
624 }
625 
626 void
627 CfgSubnets4::initAllocatorsAfterConfigure() {
628  for (auto subnet : subnets_) {
629  subnet->initAllocatorsAfterConfigure();
630  }
631 }
632 
633 void
634 CfgSubnets4::clear() {
635  subnets_.clear();
636 }
637 
639 CfgSubnets4::toElement() const {
640  ElementPtr result = Element::createList();
641  // Iterate subnets
642  for (auto const& subnet : subnets_) {
643  result->add(subnet->toElement());
644  }
645  return (result);
646 }
647 
648 } // end of namespace isc::dhcp
649 } // 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.
Holds subnets configured for the DHCPv4 server.
Definition: cfg_subnets4.h:33
const Subnet4Collection * getAll() const
Returns pointer to the collection of all IPv4 subnets.
Definition: cfg_subnets4.h:119
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
Statistics Manager class.
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
bool empty() const
Checks if the encapsulated value is empty.
Definition: optional.h:153
#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
void merge(ElementPtr element, ConstElementPtr other)
Merges the data from other into element.
Definition: data.cc:1174
boost::shared_ptr< Element > ElementPtr
Definition: data.h:26
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_INTERFACE_NO_MATCH
const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_ADDRESS_NO_MATCH
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET4_IFACE
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition: subnet.h:498
std::set< dhcp::SubnetID > SubnetIDSet
Ordered list aka set of subnetIDs.
Definition: subnet_id.h:43
const isc::log::MessageID DHCPSRV_CFGMGR_UPDATE_SUBNET4
const isc::log::MessageID DHCPSRV_CFGMGR_ADD_SUBNET4
@ DHO_DHCP_AGENT_OPTIONS
Definition: dhcp4.h:151
@ DHO_SUBNET_SELECTION
Definition: dhcp4.h:183
const isc::log::MessageID DHCPSRV_SUBNET4O6_SELECT_FAILED
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition: subnet.h:492
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition: pkt4.h:555
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
Definition: iface_mgr.h:487
const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_NO_RELAY_ADDRESS
const isc::log::MessageID DHCPSRV_CFGMGR_DEL_SUBNET4
const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_NO_USABLE_ADDRESS
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET4_ADDR
const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_NO_RAI_OPTIONS
const isc::log::MessageID DHCPSRV_CFGMGR_SUBNET4_RELAY
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
const isc::log::MessageID DHCPSRV_SUBNET4_SELECT_BY_RELAY_ADDRESS_NO_MATCH
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
boost::shared_ptr< CfgSharedNetworks4 > CfgSharedNetworks4Ptr
Pointer to the configuration of IPv4 shared networks.
@ RAI_OPTION_LINK_SELECTION
Definition: dhcp4.h:270
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition: dhcpsrv_log.h:26
boost::shared_ptr< Option > OptionPtr
Definition: option.h:36
Defines the logger used by the top-level component of kea-lfc.
This structure contains information about DHCP4o6 (RFC7341)
Definition: cfg_4o6.h:22
util::Optional< std::string > getIface4o6() const
Returns the DHCP4o6 interface.
Definition: cfg_4o6.h:45
util::Optional< std::pair< asiolink::IOAddress, uint8_t > > getSubnet4o6() const
Returns prefix/len for the IPv6 subnet.
Definition: cfg_4o6.h:58
bool enabled() const
Returns whether the DHCP4o6 is enabled or not.
Definition: cfg_4o6.h:33
OptionPtr getInterfaceId() const
Returns the interface-id.
Definition: cfg_4o6.h:72
Tag for the index for searching by subnet prefix.
Definition: subnet.h:817
Subnet selector used to specify parameters used to select a subnet.
asiolink::IOAddress local_address_
Address on which the message was received.
asiolink::IOAddress option_select_
RAI link select or subnet select option.
std::string iface_name_
Name of the interface on which the message was received.
asiolink::IOAddress ciaddr_
ciaddr from the client's message.
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 giaddr_
giaddr from the client's message.
Tag for the index for searching by server identifier.
Definition: subnet.h:820
Tag for the index for searching by subnet identifier.
Definition: subnet.h:814