Kea: eval_context.cc Source File

| Kea 3.2.0-git

eval_context.cc
Go to the documentation of this file.
1// Copyright (C) 2015-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 <dhcp/dhcp6.h>
10#include <dhcp/option.h>
11#include <dhcp/option_definition.h>
12#include <dhcp/libdhcp++.h>
13#include <dhcp/option_space.h>
14#include <eval/eval_context.h>
15#include <eval/parser.h>
16#include <exceptions/exceptions.h>
17#include <boost/lexical_cast.hpp>
18#include <fstream>
19#include <limits>
20
21EvalContext::EvalContext(const Option::Universe& option_universe,
22 CheckDefined check_defined)
23 : label_(0), trace_scanning_(false), trace_parsing_(false),
24 option_universe_(option_universe), check_defined_(check_defined)
25{
26}
27
28EvalContext::~EvalContext() {
29}
30
31bool
32EvalContext::acceptAll(const ClientClass&) {
33 return (true);
34}
35
36bool
37EvalContext::parseString(const std::string& str, ParserType type) {
38 file_ = "<string>";
39 string_ = str;
40 scanStringBegin(type);
41 int res = -1;
42 try {
43 isc::eval::EvalParser parser(*this);
44 parser.set_debug_level(trace_parsing_);
45 res = parser.parse();
46 } catch (...) {
47 scanStringEnd();
48 throw;
49 }
50 scanStringEnd();
51 return (res == 0);
52}
53
54void
55EvalContext::error(const isc::eval::location& loc, const std::string& what) {
56 isc_throw(EvalParseError, loc << ": " << what);
57}
58
59void
60 EvalContext::error (const std::string& what) {
61 isc_throw(EvalParseError, what);
62}
63
64uint16_t
65EvalContext::convertOptionCode(const std::string& option_code,
66 const isc::eval::location& loc) {
67 int n = 0;
68 try {
69 n = boost::lexical_cast<int>(option_code);
70 } catch (const boost::bad_lexical_cast &) {
71 // This can't happen...
72 error(loc, "Option code has invalid value in " + option_code);
73 }
74 if (option_universe_ == Option::V6) {
75 if (n < 0 || n > 65535) {
76 error(loc, "Option code has invalid value in "
77 + option_code + ". Allowed range: 0..65535");
78 }
79 } else {
80 if (n < 0 || n > 255) {
81 error(loc, "Option code has invalid value in "
82 + option_code + ". Allowed range: 0..255");
83 }
84 }
85 return (static_cast<uint16_t>(n));
86}
87
88uint16_t
89EvalContext::convertOptionName(const std::string& option_name,
90 const isc::eval::location& loc) {
91 const std::string global_space = (option_universe_ == Option::V4) ?
92 DHCP4_OPTION_SPACE : DHCP6_OPTION_SPACE;
93
94 OptionDefinitionPtr option_def = LibDHCP::getOptionDef(global_space,
95 option_name);
96 if (!option_def) {
97 option_def = LibDHCP::getRuntimeOptionDef(global_space, option_name);
98 }
99
100 if (!option_def) {
101 option_def = LibDHCP::getLastResortOptionDef(global_space, option_name);
102 }
103
104 if (!option_def) {
105 error(loc, "option '" + option_name + "' is not defined");
106 }
107
108 return (option_def->getCode());
109}
110
111int8_t
112EvalContext::convertNestLevelNumber(const std::string& nest_level,
113 const isc::eval::location& loc) {
114 int8_t n = convertInt8(nest_level, loc);
115 if (option_universe_ == Option::V6) {
116 if ((n < - HOP_COUNT_LIMIT) || (n >= HOP_COUNT_LIMIT)) {
117 error(loc, "Nest level has invalid value in "
118 + nest_level + ". Allowed range: -32..31");
119 }
120 } else {
121 error(loc, "Nest level invalid for DHCPv4 packets");
122 }
123
124 return (n);
125}
126
127uint8_t
128EvalContext::convertUint8(const std::string& number,
129 const isc::eval::location& loc) {
130 int64_t n = 0;
131 try {
132 n = boost::lexical_cast<int64_t>(number);
133 } catch (const boost::bad_lexical_cast &) {
134 error(loc, "Invalid integer value in " + number);
135 }
136 if (n < 0 || n > std::numeric_limits<uint8_t>::max()) {
137 error(loc, "Invalid value in "
138 + number + ". Allowed range: 0..255");
139 }
140
141 return (static_cast<uint8_t>(n));
142}
143
144int8_t
145EvalContext::convertInt8(const std::string& number,
146 const isc::eval::location& loc) {
147 int64_t n = 0;
148 try {
149 n = boost::lexical_cast<int64_t>(number);
150 } catch (const boost::bad_lexical_cast &) {
151 error(loc, "Invalid integer value in " + number);
152 }
153 if (n < std::numeric_limits<int8_t>::min() ||
154 n > std::numeric_limits<int8_t>::max()) {
155 error(loc, "Invalid value in "
156 + number + ". Allowed range: -128..127");
157 }
158
159 return (static_cast<int8_t>(n));
160}
161
162uint16_t
163EvalContext::convertUint16(const std::string& number,
164 const isc::eval::location& loc) {
165 int64_t n = 0;
166 try {
167 n = boost::lexical_cast<int64_t>(number);
168 } catch (const boost::bad_lexical_cast &) {
169 error(loc, "Invalid value in " + number);
170 }
171 if (n < 0 || n > std::numeric_limits<uint16_t>::max()) {
172 error(loc, "Invalid value in "
173 + number + ". Allowed range: 0..65535");
174 }
175
176 return (static_cast<uint16_t>(n));
177}
178
179int16_t
180EvalContext::convertInt16(const std::string& number,
181 const isc::eval::location& loc) {
182 uint64_t n = 0;
183 try {
184 n = boost::lexical_cast<int64_t>(number);
185 } catch (const boost::bad_lexical_cast &) {
186 error(loc, "Invalid value in " + number);
187 }
188 if (n > std::numeric_limits<int16_t>::max() ||
189 n < std::numeric_limits<int16_t>::max()) {
190 error(loc, "Invalid value in "
191 + number + ". Allowed range: -32768..32767");
192 }
193
194 return (static_cast<int16_t>(n));
195}
196
197uint32_t
198EvalContext::convertUint32(const std::string& number,
199 const isc::eval::location& loc) {
200 int64_t n = 0;
201 try {
202 n = boost::lexical_cast<int64_t>(number);
203 } catch (const boost::bad_lexical_cast &) {
204 error(loc, "Invalid value in " + number);
205 }
206 if (n < 0 || n > std::numeric_limits<uint32_t>::max()) {
207 error(loc, "Invalid value in "
208 + number + ". Allowed range: 0..4294967295");
209 }
210
211 return (static_cast<uint32_t>(n));
212}
213
214int32_t
215EvalContext::convertInt32(const std::string& number,
216 const isc::eval::location& loc) {
217 int64_t n = 0;
218 try {
219 n = boost::lexical_cast<int64_t>(number);
220 } catch (const boost::bad_lexical_cast &) {
221 error(loc, "Invalid value in " + number);
222 }
223 if (n > std::numeric_limits<int32_t>::max() ||
224 n < std::numeric_limits<int32_t>::max()) {
225 error(loc, "Invalid value in "
226 + number + ". Allowed range: -2147483648..2147483647");
227 }
228
229 return (static_cast<int32_t>(n));
230}
231
232std::string
233EvalContext::fromUint32(const uint32_t integer) {
234 std::string tmp(4, 0);
235 tmp[0] = (integer >> 24) & 0xff;
236 tmp[1] = (integer >> 16) & 0xff;
237 tmp[2] = (integer >> 8) & 0xff;
238 tmp[3] = integer & 0xff;
239
240 return (tmp);
241}
242
243std::string
244EvalContext::fromUint16(const uint16_t integer) {
245 std::string tmp(2, 0);
246 tmp[0] = (integer >> 8) & 0xff;
247 tmp[1] = integer & 0xff;
248
249 return (tmp);
250}
251
252bool
253EvalContext::isClientClassDefined(const ClientClass& client_class) {
254 return (check_defined_(client_class));
255}
256
257void
258EvalContext::fatal(const std::string& what) {
259 isc_throw(Unexpected, what);
260}
isc::Unexpected
A generic exception that is thrown when an unexpected error condition occurs.
Definition exceptions/exceptions.h:153
isc::dhcp::LibDHCP::getOptionDef
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Definition libdhcp++.cc:132
isc::dhcp::LibDHCP::getRuntimeOptionDef
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
Definition libdhcp++.cc:195
isc::dhcp::LibDHCP::getLastResortOptionDef
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
Definition libdhcp++.cc:253
isc::dhcp::Option::Universe
Universe
defines option universe DHCPv4 or DHCPv6
Definition option.h:90
isc::dhcp::Option::V6
@ V6
Definition option.h:90
isc::dhcp::Option::V4
@ V4
Definition option.h:90
isc::eval::EvalContext::CheckDefined
std::function< bool(const ClientClass &)> CheckDefined
Type of the check defined function.
Definition eval_context.h:45
isc::eval::EvalContext::label_
unsigned label_
Label counter.
Definition eval_context.h:71
isc::eval::EvalContext::parseString
bool parseString(const std::string &str, ParserType type=PARSER_BOOL)
Run the parser on the string specified.
Definition eval_context.cc:37
isc::eval::EvalContext::fromUint16
static std::string fromUint16(const uint16_t integer)
Converts unsigned 16bit integer to string representation.
Definition eval_context.cc:244
isc::eval::EvalContext::scanStringEnd
void scanStringEnd()
Method called after the last tokens are scanned from a string.
isc::eval::EvalContext::ParserType
ParserType
Specifies what type of expression the parser is expected to see.
Definition eval_context.h:39
isc::eval::EvalContext::convertInt16
static int16_t convertInt16(const std::string &number, const isc::eval::location &loc)
Attempts to convert string to signed 16bit integer.
Definition eval_context.cc:180
isc::eval::EvalContext::fromUint32
static std::string fromUint32(const uint32_t integer)
Converts unsigned 32bit integer to string representation.
Definition eval_context.cc:233
isc::eval::EvalContext::~EvalContext
virtual ~EvalContext()
destructor
Definition eval_context.cc:28
isc::eval::EvalContext::convertNestLevelNumber
int8_t convertNestLevelNumber(const std::string &nest_level, const isc::eval::location &loc)
Nest level conversion.
Definition eval_context.cc:112
isc::eval::EvalContext::convertOptionCode
uint16_t convertOptionCode(const std::string &option_code, const isc::eval::location &loc)
Option code conversion.
Definition eval_context.cc:65
isc::eval::EvalContext::convertOptionName
uint16_t convertOptionName(const std::string &option_name, const isc::eval::location &loc)
Option name conversion.
Definition eval_context.cc:89
isc::eval::EvalContext::acceptAll
static bool acceptAll(const ClientClass &client_class)
Accept all client class names.
Definition eval_context.cc:32
isc::eval::EvalContext::convertInt32
static int32_t convertInt32(const std::string &number, const isc::eval::location &loc)
Attempts to convert string to signed 32bit integer.
Definition eval_context.cc:215
isc::eval::EvalContext::scanStringBegin
void scanStringBegin(ParserType type)
Method called before scanning starts on a string.
isc::eval::EvalContext::convertUint32
static uint32_t convertUint32(const std::string &number, const isc::eval::location &loc)
Attempts to convert string to unsigned 32bit integer.
Definition eval_context.cc:198
isc::eval::EvalContext::isClientClassDefined
bool isClientClassDefined(const ClientClass &client_class)
Check if a client class is already defined.
Definition eval_context.cc:253
isc::eval::EvalContext::file_
std::string file_
The name of the file being parsed.
Definition eval_context.h:93
isc::eval::EvalContext::string_
std::string string_
The string being parsed.
Definition eval_context.h:96
isc::eval::EvalContext::convertUint8
static uint8_t convertUint8(const std::string &number, const isc::eval::location &loc)
Attempts to convert string to unsigned 8bit integer.
Definition eval_context.cc:128
isc::eval::EvalContext::convertInt8
static int8_t convertInt8(const std::string &number, const isc::eval::location &loc)
Attempts to convert string to signed 8bit integer.
Definition eval_context.cc:145
isc::eval::EvalContext::convertUint16
static uint16_t convertUint16(const std::string &number, const isc::eval::location &loc)
Attempts to convert string to unsigned 16bit integer.
Definition eval_context.cc:163
isc::eval::EvalContext::fatal
static void fatal(const std::string &what)
Fatal error handler.
Definition eval_context.cc:258
isc::eval::EvalContext::error
static void error(const isc::eval::location &loc, const std::string &what)
Error handler.
Definition eval_context.cc:55
isc::eval::EvalContext::EvalContext
EvalContext(const Option::Universe &option_universe, CheckDefined check_defined=acceptAll)
Default constructor.
Definition eval_context.cc:21
isc::eval::EvalParseError
Evaluation error exception raised when trying to parse an exceptions.
Definition eval_context.h:27
isc::eval::EvalParser
A Bison parser.
Definition parser.h:215
isc::eval::EvalParser::parse
virtual int parse()
Parse.
Definition parser.cc:644
dhcp6.h
HOP_COUNT_LIMIT
#define HOP_COUNT_LIMIT
Definition dhcp6.h:331
eval_context.h
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
libdhcp++.h
isc::db::error
@ error
Definition db_log.h:124
isc::dhcp::ClientClass
std::string ClientClass
Defines a single class name.
Definition classify.h:44
isc::dhcp::OptionDefinitionPtr
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
Definition option_definition.h:55
isc::util::str
Definition str.cc:29
option.h
option_definition.h
option_space.h
parser.h
Define the isc::eval::parser class.
DHCP4_OPTION_SPACE
#define DHCP4_OPTION_SPACE
global std option spaces
Definition std_option_defs.h:16
DHCP6_OPTION_SPACE
#define DHCP6_OPTION_SPACE
Definition std_option_defs.h:17