19 #include <boost/foreach.hpp>
45 << expression_cfg->str() <<
"] must be a string, at ("
46 << expression_cfg->getPosition() <<
")");
52 expression_cfg->getValue(value);
54 if (parser_type == EvalContext::PARSER_STRING && value.empty()) {
56 << expression_cfg->getPosition() <<
")");
60 EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6,
65 }
catch (
const std::exception& ex) {
68 "expression: [" << value
69 <<
"] error: " << ex.
what() <<
" at ("
70 << expression_cfg->getPosition() <<
")");
80 bool append_error_position,
81 bool check_dependencies) {
83 std::string name = getString(class_def_cfg,
"name");
86 "not empty parameter 'name' is required "
87 << getPosition(
"name", class_def_cfg) <<
")");
93 bool is_template =
false;
98 ConstElementPtr template_test_cfg = class_def_cfg->get(
"template-test");
99 if (test_cfg && template_test_cfg) {
101 << test_cfg->getPosition() <<
") and ("
102 << template_test_cfg->getPosition() <<
")");
105 bool depend_on_known =
false;
107 if (template_test_cfg) {
108 test_cfg = template_test_cfg;
109 parser_type = EvalContext::PARSER_STRING;
112 check_defined = [&class_dictionary, &depend_on_known, check_dependencies](
const ClientClass& cclass) {
113 return (!check_dependencies ||
isClientClassDefined(class_dictionary, depend_on_known, cclass));
119 parser.
parse(match_expr, test_cfg, family, check_defined, parser_type);
120 test = test_cfg->stringValue();
130 SimpleParser4::OPTION4_DEF_DEFAULTS :
131 SimpleParser6::OPTION6_DEF_DEFAULTS);
139 if (!LibDHCP::shouldDeferOptionUnpack(def->getOptionSpaceName(),
142 "Not allowed option definition for code '"
143 << def->getCode() <<
"' in space '"
144 << def->getOptionSpaceName() <<
"' at ("
145 << option_def->getPosition() <<
")");
149 }
catch (
const std::exception& ex) {
152 << option_def->getPosition() <<
")");
161 auto opts_parser = createOptionDataListParser(family, defs);
162 opts_parser->parse(options, option_data);
170 << user_context->getPosition() <<
")");
175 bool required =
false;
176 if (class_def_cfg->contains(
"only-if-required")) {
177 required = getBoolean(class_def_cfg,
"only-if-required");
182 if (class_def_cfg->contains(
"next-server")) {
183 std::string next_server_txt = getString(class_def_cfg,
"next-server");
185 next_server =
IOAddress(next_server_txt);
188 "Invalid next-server value specified: '"
189 << next_server_txt <<
"' ("
190 << getPosition(
"next-server", class_def_cfg) <<
")");
193 if (next_server.
getFamily() != AF_INET) {
195 << next_server_txt <<
"', must be IPv4 address ("
196 << getPosition(
"next-server", class_def_cfg) <<
")");
201 << next_server_txt <<
"', must not be a broadcast ("
202 << getPosition(
"next-server", class_def_cfg) <<
")");
208 if (class_def_cfg->contains(
"server-hostname")) {
209 sname = getString(class_def_cfg,
"server-hostname");
211 if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
213 << Pkt4::MAX_SNAME_LEN - 1 <<
" bytes long, it is "
214 << sname.length() <<
" ("
215 << getPosition(
"server-hostname", class_def_cfg) <<
")");
220 std::string filename;
221 if (class_def_cfg->contains(
"boot-file-name")) {
222 filename = getString(class_def_cfg,
"boot-file-name");
224 if (filename.length() > Pkt4::MAX_FILE_LEN) {
226 << Pkt4::MAX_FILE_LEN - 1 <<
" bytes long, it is "
227 << filename.length() <<
" ("
228 << getPosition(
"boot-file-name", class_def_cfg) <<
")");
233 if (class_def_cfg->contains(
"offer-lifetime")) {
234 auto value = getInteger(class_def_cfg,
"offer-lifetime");
237 << value <<
"' must be a positive number ("
238 << getPosition(
"offer-lifetime", class_def_cfg) <<
")");
248 if (family != AF_INET) {
250 preferred_lft = parseIntTriplet(class_def_cfg,
"preferred-lifetime");
258 <<
"' only-if-required flag must be false");
262 <<
"' test expression must be empty");
268 if (name ==
"DROP") {
271 <<
"' only-if-required flag must be false");
278 class_dictionary->addClass(name, match_expr, test, required,
279 depend_on_known, options, defs,
280 user_context, next_server, sname, filename,
281 valid_lft, preferred_lft, is_template, offer_lft);
282 }
catch (
const std::exception& ex) {
283 std::ostringstream s;
284 s <<
"Can't add class: " << ex.what();
286 if (append_error_position) {
287 s <<
" (" << class_def_cfg->getPosition() <<
")";
295 const uint16_t family) {
297 if (!class_def_cfg || (class_def_cfg->getType() !=
Element::map)) {
302 static std::set<std::string> supported_params = {
"name",
308 "min-valid-lifetime",
309 "max-valid-lifetime",
313 static std::set<std::string> supported_params_v4 = {
"option-def",
319 static std::set<std::string> supported_params_v6 = {
"preferred-lifetime",
320 "min-preferred-lifetime",
321 "max-preferred-lifetime" };
324 for (
auto name_value_pair : class_def_cfg->mapValue()) {
325 if ((supported_params.count(name_value_pair.first) > 0) ||
326 ((family == AF_INET) && (supported_params_v4.count(name_value_pair.first) > 0)) ||
327 ((family != AF_INET) && (supported_params_v6.count(name_value_pair.first) > 0))) {
331 << name_value_pair.first <<
"'");
336 boost::shared_ptr<OptionDataListParser>
337 ClientClassDefParser::createOptionDataListParser(
const uint16_t address_family,
339 auto parser = boost::make_shared<OptionDataListParser>(address_family, cfg_option_def);
347 uint16_t family,
bool check_dependencies) {
350 client_class_def_list->listValue()) {
352 parser.
parse(dictionary, client_class_def, family,
true, check_dependencies);
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The IOAddress class represents an IP addresses (version agnostic)
bool isV4Bcast() const
Convenience function to check if it is an IPv4 broadcast address.
short getFamily() const
Returns the address family.
An exception that is thrown if an error occurs within the IO module.
static size_t setListDefaults(isc::data::ConstElementPtr list, const SimpleDefaults &default_values)
Sets the default values for all entries in a list.
Represents option definitions used by the DHCP server.
Represents option data configuration for the DHCP server.
Parser for a single client class definition.
void parse(ClientClassDictionaryPtr &class_dictionary, isc::data::ConstElementPtr client_class_def, uint16_t family, bool append_error_position=true, bool check_dependencies=true)
Parses an entry that describes single client class definition.
Maintains a list of ClientClassDef's.
To be removed. Please use ConfigError instead.
Parser for a logical expression.
void parse(ExpressionPtr &expression, isc::data::ConstElementPtr expression_cfg, uint16_t family, isc::eval::EvalContext::CheckDefined check_defined=isc::eval::EvalContext::acceptAll, isc::eval::EvalContext::ParserType parser_type=isc::eval::EvalContext::PARSER_BOOL)
Parses an expression configuration element into an Expression.
Parser for a single option definition.
OptionDefinitionPtr parse(isc::data::ConstElementPtr option_def)
Parses an entry that describes single option definition.
Evaluation context, an interface to the expression evaluation.
std::function< bool(const ClientClass &)> CheckDefined
Type of the check defined function.
bool parseString(const std::string &str, ParserType type=PARSER_BOOL)
Run the parser on the string specified.
ParserType
Specifies what type of expression the parser is expected to see.
isc::dhcp::Expression expression
Parsed expression (output tokens are stored here)
Defines classes for storing client class definitions.
Parsers for client class definitions.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
std::string ClientClass
Defines a single class name.
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::shared_ptr< Expression > ExpressionPtr
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
bool isClientClassDefined(ClientClassDictionaryPtr &class_dictionary, bool &depend_on_known, const ClientClass &client_class)
Check if a client class name is already defined, i.e.
std::vector< TokenPtr > Expression
This is a structure that holds an expression converted to RPN.
std::list< std::string > builtinNames
List of classes for which test expressions cannot be defined.
Defines the logger used by the top-level component of kea-lfc.