Kea: host_cache_parsers.cc Source File

| Kea 3.2.0-git

host_cache_parsers.cc
Go to the documentation of this file.
1// Copyright (C) 2020-2025 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
9#include <host_cache_parsers.h>
10#include <cc/dhcp_config_error.h>
11#include <dhcpsrv/parsers/option_data_parser.h>
12#include <boost/pointer_cast.hpp>
13#include <boost/lexical_cast.hpp>
14
15using namespace isc::asiolink;
16using namespace isc::data;
17using namespace isc::dhcp;
18using namespace std;
19
20namespace isc {
21namespace host_cache {
22
24const SimpleDefaults HCConfigParser::HOST_CACHE_DEFAULTS = {
25 { "maximum", Element::integer, "0" }
26};
27
29void
30HCConfigParser::parse(HostCache& hcref, const ConstElementPtr& config) {
31 ElementPtr mutable_cfg;
32 if (config) {
33 mutable_cfg = boost::const_pointer_cast<Element>(config);
34 } else {
35 mutable_cfg = Element::createMap();
36 }
37
38 if (!mutable_cfg || (mutable_cfg->getType() != Element::map)) {
39 isc_throw(ConfigError, "Host Cache config is not a map");
40 }
41
42 try {
43 setDefaults(mutable_cfg, HOST_CACHE_DEFAULTS);
44
45 int64_t maximum = getInteger(mutable_cfg, "maximum");
46 if (maximum < 0) {
47 isc_throw(ConfigError, "Host Cache maximum parameter is negative");
48 }
49 if (maximum > MAXIMUM) {
50 isc_throw(ConfigError, "Host Cache maximum parameter is too large "
51 << "(" << maximum << " > " << MAXIMUM << ")");
52 }
53 hcref.setMaximum(static_cast<size_t>(maximum));
54 } catch (const ConfigError&) {
55 throw;
56 } catch (const exception& ex) {
57 isc_throw(ConfigError, ex.what());
58 }
59}
60
61 HostPtr
62HCEntryParser::parse(const ConstElementPtr& entry) {
63 try {
64 // Scan critical parameters
65 string identifier;
66 string identifier_name;
67 string hostname;
68 ConstElementPtr user_context;
69 auto& map = entry->mapValue();
70 for (auto const& element : map) {
71 if ((element.first == "hw-address") ||
72 (element.first == "duid") ||
73 (element.first == "circuit-id") ||
74 (element.first == "client-id") ||
75 (element.first == "flex-id")) {
76 if (!identifier_name.empty()) {
77 isc_throw(ConfigError, "the '" << element.first
78 << "' and '" << identifier_name
79 << "' are mutually exclusive");
80 }
81 identifier = element.second->stringValue();
82 identifier_name = element.first;
83 continue;
84 }
85
86 if (element.first == "hostname") {
87 hostname = element.second->stringValue();
88 continue;
89 }
90
91 if (element.first == "user-context") {
92 user_context = element.second;
93 continue;
94 }
95 }
96
97 // Host identifier is a must.
98 if (identifier_name.empty()) {
99 isc_throw(ConfigError, "no identifier");
100 }
101
102 // Create a host object from the basic parameters we already parsed.
103 HostPtr host;
104 host.reset(new Host(identifier, identifier_name,
105 SubnetID(SUBNET_ID_UNUSED),
106 SubnetID(SUBNET_ID_UNUSED),
107 IOAddress("0.0.0.0"), hostname));
108 // Add user context
109 if (user_context) {
110 host->setContext(user_context);
111 }
112
113 // Scan other parameters
114 for (auto const& element : map) {
115 if ((element.first == "hw-address") ||
116 (element.first == "duid") ||
117 (element.first == "circuit-id") ||
118 (element.first == "client-id") ||
119 (element.first == "flex-id") ||
120 (element.first == "hostname") ||
121 (element.first == "user-context")) {
122 continue;
123 }
124
125 if (element.first == "subnet-id4") {
126 host->setIPv4SubnetID(element.second->intValue());
127 continue;
128 }
129
130 if (element.first == "subnet-id6") {
131 host->setIPv6SubnetID(element.second->intValue());
132 continue;
133 }
134
135 if (element.first == "option-data4") {
136 CfgOptionPtr cfg_option = host->getCfgOption4();
137 OptionDataListParser parser(AF_INET);
138 parser.parse(cfg_option, element.second);
139 continue;
140 }
141
142 if (element.first == "option-data6") {
143 CfgOptionPtr cfg_option = host->getCfgOption6();
144 OptionDataListParser parser(AF_INET6);
145 parser.parse(cfg_option, element.second);
146 continue;
147 }
148
149 if (element.first == "ip-address") {
150 host->setIPv4Reservation(IOAddress(element.second->stringValue()));
151 continue;
152 }
153
154 if (element.first == "next-server") {
155 host->setNextServer(IOAddress(element.second->stringValue()));
156 continue;
157 }
158
159 if (element.first == "server-hostname") {
160 host->setServerHostname(element.second->stringValue());
161 continue;
162 }
163
164 if (element.first == "boot-file-name") {
165 host->setBootFileName(element.second->stringValue());
166 continue;
167 }
168
169 if (element.first == "client-classes4") {
170 auto const& classes = element.second->listValue();
171 for (auto const& cclass : classes) {
172 host->addClientClass4(cclass->stringValue());
173 }
174 continue;
175 }
176
177 if (element.first == "client-classes6") {
178 auto const& classes = element.second->listValue();
179 for (auto const& cclass : classes) {
180 host->addClientClass6(cclass->stringValue());
181 }
182 continue;
183 }
184
185 if (element.first == "ip-addresses") {
186 auto const& addresses = element.second->listValue();
187 for (auto const& addr : addresses) {
188 string address = addr->stringValue();
189 host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA,
190 IOAddress(address),
191 128));
192 }
193 continue;
194 }
195
196 if (element.first == "prefixes") {
197 auto& prefixes = element.second->listValue();
198 for (auto const& pref : prefixes) {
199 string prefix = pref->stringValue();
200 uint8_t len = 128;
201 size_t pos = prefix.find('/');
202 if (pos == string::npos) {
203 isc_throw(ConfigError, "bad prefix (no /)");
204 } else if (pos > prefix.length() - 1) {
205 isc_throw(ConfigError, "bad prefix (end /)");
206 }
207 try {
208 string preflen = prefix.substr(pos + 1);
209 len = boost::lexical_cast<unsigned>(preflen);
210 } catch (const boost::bad_lexical_cast&) {
211 isc_throw(ConfigError, "bad prefix length");
212 }
213 prefix.erase(pos);
214
215 host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_PD,
216 IOAddress(prefix),
217 len));
218 }
219 continue;
220 }
221
222 if (element.first == "host-id") {
223 int64_t hid = element.second->intValue();
224 host->setHostId(static_cast<uint64_t>(hid));
225 continue;
226 }
227
228 if (element.first == "negative") {
229 host->setNegative(element.second->boolValue());
230 continue;
231 }
232
233 isc_throw(ConfigError, "unknown parameter: " << element.first);
234 }
235 return (host);
236
237 } catch (const ConfigError&) {
238 throw;
239 } catch (const exception& ex) {
240 isc_throw(ConfigError, ex.what());
241 }
242}
243
244} // end of namespace isc::host_cache
245} // end of namespace isc
Element::map
@ map
Definition data.h:160
Element::integer
@ integer
Definition data.h:153
Element::createMap
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
isc::ConfigError
An exception that is thrown if an error occurs while configuring any server.
Definition dhcp_config_error.h:43
isc::asiolink::IOAddress
The IOAddress class represents an IP addresses (version agnostic).
Definition io_address.h:53
isc::data::SimpleParser::getInteger
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
Definition lib/cc/simple_parser.cc:77
isc::data::SimpleParser::setDefaults
static size_t setDefaults(isc::data::ElementPtr scope, const SimpleDefaults &default_values)
Sets the default values.
Definition lib/cc/simple_parser.cc:170
isc::dhcp::Host
Represents a device with IPv4 and/or IPv6 reservations.
Definition host.h:327
isc::dhcp::IPv6Resrv
IPv6 reservation for a host.
Definition host.h:163
isc::dhcp::IPv6Resrv::TYPE_PD
@ TYPE_PD
Definition host.h:171
isc::dhcp::IPv6Resrv::TYPE_NA
@ TYPE_NA
Definition host.h:170
isc::dhcp::OptionDataListParser
Parser for option data values within a subnet.
Definition option_data_parser.h:191
isc::dhcp::OptionDataListParser::parse
void parse(const CfgOptionPtr &cfg, isc::data::ConstElementPtr option_data_list, bool encapsulate=true)
Parses a list of options, instantiates them and stores in cfg.
Definition option_data_parser.cc:459
isc::host_cache::HCConfigParser::MAXIMUM
static const int64_t MAXIMUM
Absolute maximum number of elements.
Definition host_cache_parsers.h:34
isc::host_cache::HCConfigParser::HOST_CACHE_DEFAULTS
static const data::SimpleDefaults HOST_CACHE_DEFAULTS
Defaults for Host Cache configuration.
Definition host_cache_parsers.h:31
isc::host_cache::HCConfigParser::parse
void parse(HostCache &hcref, const data::ConstElementPtr &config)
Parses Host Cache configuration.
Definition host_cache_parsers.cc:30
isc::host_cache::HCEntryParser::parse
dhcp::HostPtr parse(const data::ConstElementPtr &entry)
Parses Host Cache entry.
Definition host_cache_parsers.cc:62
isc::host_cache::HostCache
Host Cache implementation.
Definition host_cache.h:35
isc::host_cache::HostCache::setMaximum
virtual void setMaximum(size_t maximum)
Set maximum number of cached hosts (0 means unbound).
Definition host_cache.cc:47
dhcp_config_error.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
host_cache_parsers.h
isc::asiolink
Definition addr_utilities.cc:170
isc::config
Definition command_interpreter.cc:23
isc::data
Definition base_stamped_element.cc:12
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
isc::data::SimpleDefaults
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet).
Definition lib/cc/simple_parser.h:39
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
isc::dhcp
Definition dhcp4/client_handler.cc:20
isc::dhcp::CfgOptionPtr
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition cfg_option.h:973
isc::dhcp::HostPtr
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition host.h:837
isc::dhcp::SubnetID
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
isc::host_cache
Definition container.h:22
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18
option_data_parser.h