Commit 28a9a845 authored by Francis Dupont's avatar Francis Dupont
Browse files

[master] Finishing merge of trac5098 (migrate client class def)

parents 3d161738 9adb0eb5
1207. [func] fdupont
Client classes parser migrated to SimpleParser. The 'name'
parameter in 'client-classes' definitions is now mandatory.
(Trac #5098, git xxx)
1206. [func] tomek
'hooks-libraries' parser migrated to SimpleParser. The code will
now refuse a configuration if a hook library fails to load.
......
This diff is collapsed.
......@@ -40,7 +40,7 @@
#ifndef YY_PARSER4_DHCP4_PARSER_H_INCLUDED
# define YY_PARSER4_DHCP4_PARSER_H_INCLUDED
// // "%code requires" blocks.
#line 17 "dhcp4_parser.yy" // lalr1.cc:377
#line 17 "dhcp4_parser.yy" // lalr1.cc:392
#include <string>
#include <cc/data.h>
......@@ -52,7 +52,7 @@ using namespace isc::dhcp;
using namespace isc::data;
using namespace std;
#line 56 "dhcp4_parser.h" // lalr1.cc:377
#line 56 "dhcp4_parser.h" // lalr1.cc:392
# include <cassert>
# include <cstdlib> // std::abort
......@@ -135,9 +135,9 @@ using namespace std;
# endif /* ! defined YYDEBUG */
#endif /* ! defined PARSER4_DEBUG */
#line 14 "dhcp4_parser.yy" // lalr1.cc:377
#line 14 "dhcp4_parser.yy" // lalr1.cc:392
namespace isc { namespace dhcp {
#line 141 "dhcp4_parser.h" // lalr1.cc:377
#line 141 "dhcp4_parser.h" // lalr1.cc:392
......@@ -1312,8 +1312,8 @@ namespace isc { namespace dhcp {
enum
{
yyeof_ = 0,
yylast_ = 728, ///< Last index in yytable_.
yynnts_ = 303, ///< Number of nonterminal symbols.
yylast_ = 732, ///< Last index in yytable_.
yynnts_ = 305, ///< Number of nonterminal symbols.
yyfinal_ = 24, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
......@@ -1408,9 +1408,9 @@ namespace isc { namespace dhcp {
switch (other.type_get ())
{
case 145: // value
case 184: // socket_type
case 397: // ncr_protocol_value
case 406: // replace_client_name_value
case 186: // socket_type
case 399: // ncr_protocol_value
case 408: // replace_client_name_value
value.copy< ElementPtr > (other.value);
break;
......@@ -1448,9 +1448,9 @@ namespace isc { namespace dhcp {
switch (this->type_get ())
{
case 145: // value
case 184: // socket_type
case 397: // ncr_protocol_value
case 406: // replace_client_name_value
case 186: // socket_type
case 399: // ncr_protocol_value
case 408: // replace_client_name_value
value.copy< ElementPtr > (v);
break;
......@@ -1547,9 +1547,9 @@ namespace isc { namespace dhcp {
switch (yytype)
{
case 145: // value
case 184: // socket_type
case 397: // ncr_protocol_value
case 406: // replace_client_name_value
case 186: // socket_type
case 399: // ncr_protocol_value
case 408: // replace_client_name_value
value.template destroy< ElementPtr > ();
break;
......@@ -1593,9 +1593,9 @@ namespace isc { namespace dhcp {
switch (this->type_get ())
{
case 145: // value
case 184: // socket_type
case 397: // ncr_protocol_value
case 406: // replace_client_name_value
case 186: // socket_type
case 399: // ncr_protocol_value
case 408: // replace_client_name_value
value.move< ElementPtr > (s.value);
break;
......@@ -2469,9 +2469,9 @@ namespace isc { namespace dhcp {
}
#line 14 "dhcp4_parser.yy" // lalr1.cc:377
#line 14 "dhcp4_parser.yy" // lalr1.cc:392
} } // isc::dhcp
#line 2475 "dhcp4_parser.h" // lalr1.cc:377
#line 2475 "dhcp4_parser.h" // lalr1.cc:392
......
......@@ -274,14 +274,6 @@ list_generic: LSQUARE_BRACKET {
// list parsing complete. Put any sanity checking here
};
// This one is used in syntax parser.
list2: LSQUARE_BRACKET {
// List parsing about to start
} list_content RSQUARE_BRACKET {
// list parsing complete. Put any sanity checking here
//ctx.stack_.pop_back();
};
list_content: %empty // Empty list
| not_empty_list
;
......@@ -296,6 +288,28 @@ not_empty_list: value {
}
;
// This one is used in syntax parser and is restricted to strings.
list_strings: LSQUARE_BRACKET {
// List parsing about to start
} list_strings_content RSQUARE_BRACKET {
// list parsing complete. Put any sanity checking here
//ctx.stack_.pop_back();
};
list_strings_content: %empty // Empty list
| not_empty_list_strings
;
not_empty_list_strings: STRING {
ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
ctx.stack_.back()->add(s);
}
| not_empty_list_strings COMMA STRING {
ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->add(s);
}
;
// ---- generic JSON parser ends here ----------------------------------
// ---- syntax checking parser starts here -----------------------------
......@@ -452,7 +466,7 @@ interfaces_list: INTERFACES {
ctx.stack_.back()->set("interfaces", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
......@@ -1260,7 +1274,7 @@ reservation_client_classes: CLIENT_CLASSES {
ctx.stack_.back()->set("client-classes", c);
ctx.stack_.push_back(c);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
......
......@@ -437,8 +437,7 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
parser = new BooleanParser(config_id, globalContext()->boolean_values_);
// control-socket has been converted to SimpleParser already.
// expired-leases-processing has been converted to SimpleParser already.
} else if (config_id.compare("client-classes") == 0) {
parser = new ClientClassDefListParser(config_id, globalContext());
// client-classes has been converted to SimpleParser already.
// host-reservation-identifiers have been converted to SimpleParser already.
} else {
isc_throw(DhcpConfigError,
......@@ -568,7 +567,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
ParserCollection independent_parsers;
ParserPtr subnet_parser;
ParserPtr leases_parser;
ParserPtr client_classes_parser;
// Some of the parsers alter the state of the system in a way that can't
// easily be undone. (Or alter it in a way such that undoing the change has
......@@ -677,6 +675,14 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
continue;
}
if (config_pair.first == "client-classes") {
ClientClassDefListParser parser;
ClientClassDictionaryPtr dictionary =
parser.parse(config_pair.second, AF_INET);
CfgMgr::instance().getStagingCfg()->setClientClassDictionary(dictionary);
continue;
}
ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
......@@ -685,8 +691,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
subnet_parser = parser;
} else if (config_pair.first == "lease-database") {
leases_parser = parser;
} else if (config_pair.first == "client-classes") {
client_classes_parser = parser;
} else {
// Those parsers should be started before other
// parsers so we can call build straight away.
......@@ -699,15 +703,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
}
}
// The class definitions parser is the next one to be run.
std::map<std::string, ConstElementPtr>::const_iterator cc_config =
values_map.find("client-classes");
if (cc_config != values_map.end()) {
config_pair.first = "client-classes";
client_classes_parser->build(cc_config->second);
client_classes_parser->commit();
}
// The subnet parser is the next one to be run.
std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
values_map.find("subnet4");
......
This diff is collapsed.
......@@ -40,7 +40,7 @@
#ifndef YY_PARSER6_DHCP6_PARSER_H_INCLUDED
# define YY_PARSER6_DHCP6_PARSER_H_INCLUDED
// // "%code requires" blocks.
#line 17 "dhcp6_parser.yy" // lalr1.cc:377
#line 17 "dhcp6_parser.yy" // lalr1.cc:392
#include <string>
#include <cc/data.h>
......@@ -52,7 +52,7 @@ using namespace isc::dhcp;
using namespace isc::data;
using namespace std;
#line 56 "dhcp6_parser.h" // lalr1.cc:377
#line 56 "dhcp6_parser.h" // lalr1.cc:392
# include <cassert>
# include <cstdlib> // std::abort
......@@ -135,9 +135,9 @@ using namespace std;
# endif /* ! defined YYDEBUG */
#endif /* ! defined PARSER6_DEBUG */
#line 14 "dhcp6_parser.yy" // lalr1.cc:377
#line 14 "dhcp6_parser.yy" // lalr1.cc:392
namespace isc { namespace dhcp {
#line 141 "dhcp6_parser.h" // lalr1.cc:377
#line 141 "dhcp6_parser.h" // lalr1.cc:392
......@@ -1327,8 +1327,8 @@ namespace isc { namespace dhcp {
enum
{
yyeof_ = 0,
yylast_ = 742, ///< Last index in yytable_.
yynnts_ = 310, ///< Number of nonterminal symbols.
yylast_ = 752, ///< Last index in yytable_.
yynnts_ = 312, ///< Number of nonterminal symbols.
yyfinal_ = 26, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
......@@ -1423,9 +1423,9 @@ namespace isc { namespace dhcp {
switch (other.type_get ())
{
case 149: // value
case 374: // duid_type
case 407: // ncr_protocol_value
case 416: // replace_client_name_value
case 376: // duid_type
case 409: // ncr_protocol_value
case 418: // replace_client_name_value
value.copy< ElementPtr > (other.value);
break;
......@@ -1463,9 +1463,9 @@ namespace isc { namespace dhcp {
switch (this->type_get ())
{
case 149: // value
case 374: // duid_type
case 407: // ncr_protocol_value
case 416: // replace_client_name_value
case 376: // duid_type
case 409: // ncr_protocol_value
case 418: // replace_client_name_value
value.copy< ElementPtr > (v);
break;
......@@ -1562,9 +1562,9 @@ namespace isc { namespace dhcp {
switch (yytype)
{
case 149: // value
case 374: // duid_type
case 407: // ncr_protocol_value
case 416: // replace_client_name_value
case 376: // duid_type
case 409: // ncr_protocol_value
case 418: // replace_client_name_value
value.template destroy< ElementPtr > ();
break;
......@@ -1608,9 +1608,9 @@ namespace isc { namespace dhcp {
switch (this->type_get ())
{
case 149: // value
case 374: // duid_type
case 407: // ncr_protocol_value
case 416: // replace_client_name_value
case 376: // duid_type
case 409: // ncr_protocol_value
case 418: // replace_client_name_value
value.move< ElementPtr > (s.value);
break;
......@@ -2502,9 +2502,9 @@ namespace isc { namespace dhcp {
}
#line 14 "dhcp6_parser.yy" // lalr1.cc:377
#line 14 "dhcp6_parser.yy" // lalr1.cc:392
} } // isc::dhcp
#line 2508 "dhcp6_parser.h" // lalr1.cc:377
#line 2508 "dhcp6_parser.h" // lalr1.cc:392
......
......@@ -277,14 +277,6 @@ list_generic: LSQUARE_BRACKET {
// list parsing complete. Put any sanity checking here
};
// This one is used in syntax parser.
list2: LSQUARE_BRACKET {
// List parsing about to start
} list_content RSQUARE_BRACKET {
// list parsing complete. Put any sanity checking here
//ctx.stack_.pop_back();
};
list_content: %empty // Empty list
| not_empty_list
;
......@@ -299,6 +291,28 @@ not_empty_list: value {
}
;
// This one is used in syntax parser and is restricted to strings.
list_strings: LSQUARE_BRACKET {
// List parsing about to start
} list_strings_content RSQUARE_BRACKET {
// list parsing complete. Put any sanity checking here
//ctx.stack_.pop_back();
};
list_strings_content: %empty // Empty list
| not_empty_list_strings
;
not_empty_list_strings: STRING {
ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
ctx.stack_.back()->add(s);
}
| not_empty_list_strings COMMA STRING {
ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->add(s);
}
;
// ---- generic JSON parser ends here ----------------------------------
// ---- syntax checking parser starts here -----------------------------
......@@ -441,7 +455,7 @@ interface_config_map: INTERFACES {
ctx.stack_.back()->set("interfaces", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
......@@ -587,12 +601,14 @@ hw_address_id : HW_ADDRESS {
ctx.stack_.back()->add(hwaddr);
};
// list_content below accepts any value when options are by name (string)
// or by code (number)
relay_supplied_options: RELAY_SUPPLIED_OPTIONS {
ElementPtr l(new ListElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("relay-supplied-options", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON LSQUARE_BRACKET list_content RSQUARE_BRACKET {
ctx.stack_.pop_back();
ctx.leave();
};
......@@ -1244,7 +1260,7 @@ ip_addresses: IP_ADDRESSES {
ctx.stack_.back()->set("ip-addresses", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
......@@ -1254,7 +1270,7 @@ prefixes: PREFIXES {
ctx.stack_.back()->set("prefixes", l);
ctx.stack_.push_back(l);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
......@@ -1288,7 +1304,7 @@ reservation_client_classes: CLIENT_CLASSES {
ctx.stack_.back()->set("client-classes", c);
ctx.stack_.push_back(c);
ctx.enter(ctx.NO_KEYWORD);
} COLON list2 {
} COLON list_strings {
ctx.stack_.pop_back();
ctx.leave();
};
......
......@@ -716,8 +716,7 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
parser = new RSOOListConfigParser(config_id);
// control-socket has been converted to SimpleParser.
// expired-leases-processing has been converted to SimpleParser.
} else if (config_id.compare("client-classes") == 0) {
parser = new ClientClassDefListParser(config_id, globalContext());
// client-classes has been converted to SimpleParser.
// host-reservation-identifiers have been converted to SimpleParser already.
// server-id has been migrated to SimpleParser
} else {
......@@ -837,7 +836,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
ParserCollection independent_parsers;
ParserPtr subnet_parser;
ParserPtr leases_parser;
ParserPtr client_classes_parser;
// Some of the parsers alter state of the system that can't easily
// be undone. (Or alter it in a way such that undoing the change
......@@ -959,6 +957,14 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
continue;
}
if (config_pair.first =="client-classes") {
ClientClassDefListParser parser;
ClientClassDictionaryPtr dictionary =
parser.parse(config_pair.second, AF_INET6);
CfgMgr::instance().getStagingCfg()->setClientClassDictionary(dictionary);
continue;
}
ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
......@@ -967,8 +973,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
subnet_parser = parser;
} else if (config_pair.first == "lease-database") {
leases_parser = parser;
} else if (config_pair.first == "client-classes") {
client_classes_parser = parser;
} else {
// Those parsers should be started before other
// parsers so we can call build straight away.
......@@ -981,15 +985,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
}
}
// The class definitions parser is the next one to be run.
std::map<std::string, ConstElementPtr>::const_iterator cc_config =
values_map.find("client-classes");
if (cc_config != values_map.end()) {
config_pair.first = "client-classes";
client_classes_parser->build(cc_config->second);
client_classes_parser->commit();
}
// The subnet parser is the next one to be run.
std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
values_map.find("subnet6");
......
// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <cc/data.h>
#include <config.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/client_class_def.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/parsers/client_class_def_parser.h>
#include <eval/eval_context.h>
#include <asiolink/io_address.h>
......@@ -18,7 +19,7 @@ using namespace isc::data;
using namespace isc::asiolink;
using namespace std;
/// @file client_class_def.cc
/// @file client_class_def_parser.cc
///
/// @brief Method implementations for client class definition parsing
......@@ -27,14 +28,10 @@ namespace dhcp {
// ********************** ExpressionParser ****************************
ExpressionParser::ExpressionParser(const std::string&,
ExpressionPtr& expression, ParserContextPtr global_context)
: local_expression_(ExpressionPtr()), expression_(expression),
global_context_(global_context) {
}
void
ExpressionParser::build(ConstElementPtr expression_cfg) {
ExpressionParser::parse(ExpressionPtr& expression,
ConstElementPtr expression_cfg,
uint16_t family) {
if (expression_cfg->getType() != Element::string) {
isc_throw(DhcpConfigError, "expression ["
<< expression_cfg->str() << "] must be a string, at ("
......@@ -46,10 +43,10 @@ ExpressionParser::build(ConstElementPtr expression_cfg) {
std::string value;
expression_cfg->getValue(value);
try {
EvalContext eval_ctx(global_context_->universe_);
EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6);
eval_ctx.parseString(value);
local_expression_.reset(new Expression());
*local_expression_ = eval_ctx.expression;
expression.reset(new Expression());
*expression = eval_ctx.expression;
} catch (const std::exception& ex) {
// Append position if there is a failure.
isc_throw(DhcpConfigError,
......@@ -59,74 +56,60 @@ ExpressionParser::build(ConstElementPtr expression_cfg) {
}
}
void
ExpressionParser::commit() {
expression_ = local_expression_;
}
// ********************** ClientClassDefParser ****************************
ClientClassDefParser::ClientClassDefParser(const std::string&,
ClientClassDictionaryPtr& class_dictionary, ParserContextPtr global_context)
: string_values_(new StringStorage()),
match_expr_(ExpressionPtr()),
options_(new CfgOption()),
class_dictionary_(class_dictionary),
global_context_(global_context) {
}
void
ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
// Parse the elements that make up the option definition.
BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
std::string entry(param.first);
ParserPtr parser;
if (entry == "name") {
StringParserPtr str_parser(new StringParser(entry, string_values_));
parser = str_parser;
} else if (entry == "test") {
ExpressionParserPtr exp_parser(new ExpressionParser(entry,
match_expr_,
global_context_));
parser = exp_parser;
} else if (entry == "option-data") {
uint16_t family = (global_context_->universe_ == Option::V4 ?
AF_INET : AF_INET6);
OptionDataListParser opts_parser(family);
opts_parser.parse(options_, param.second);
// OptionDataListParser is converted to SimpleParser already,
// no need to go through build/commit phases.
continue;
} else if (entry == "next-server") {
StringParserPtr str_parser(new StringParser(entry, string_values_));
parser = str_parser;
} else if (entry == "server-hostname") {
StringParserPtr str_parser(new StringParser(entry, string_values_));
parser = str_parser;
} else if (entry == "boot-file-name") {
StringParserPtr str_parser(new StringParser(entry, string_values_));
parser = str_parser;
} else {
isc_throw(DhcpConfigError, "invalid parameter '" << entry
<< "' (" << param.second->getPosition() << ")");
}
ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
ConstElementPtr class_def_cfg,
uint16_t family) {
parser->build(param.second);
parser->commit();
}
std::string name;
try {
name = string_values_->getParam("name");
std::string name;
std::string next_server_txt = "0.0.0.0";
std::string sname;
std::string filename;
ExpressionPtr match_expr;
CfgOptionPtr options(new CfgOption());
// Parse the elements that make up the client class definition.
BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
std::string entry(param.first);
ConstElementPtr value(param.second);
if (entry == "name") {
name = value->stringValue();
} else if (entry == "test") {
ExpressionParser parser;