Commit fa41a74a authored by Francis Dupont's avatar Francis Dupont
Browse files

[5098] Specialized list2 to string only - migrated global client class defs

parent 0fac7208
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
......@@ -1159,8 +1159,8 @@ namespace isc { namespace dhcp {
enum
{
yyeof_ = 0,
yylast_ = 624, ///< Last index in yytable_.
yynnts_ = 267, ///< Number of nonterminal symbols.
yylast_ = 628, ///< Last index in yytable_.
yynnts_ = 269, ///< Number of nonterminal symbols.
yyfinal_ = 22, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
......@@ -2118,9 +2118,9 @@ namespace isc { namespace dhcp {
}
#line 14 "dhcp4_parser.yy" // lalr1.cc:377
#line 14 "dhcp4_parser.yy" // lalr1.cc:392
} } // isc::dhcp
#line 2124 "dhcp4_parser.h" // lalr1.cc:377
#line 2124 "dhcp4_parser.h" // lalr1.cc:392
......
/* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
/* Copyright (C) 2016-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
......@@ -260,14 +260,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
;
......@@ -282,6 +274,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 -----------------------------
......@@ -438,7 +452,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();
};
......@@ -1213,7 +1227,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();
};
......
......@@ -441,8 +441,7 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
// control-socket has been converted to SimpleParser already.
} else if (config_id.compare("expired-leases-processing") == 0) {
parser = new ExpirationConfigParser();
} 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,
......@@ -573,7 +572,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
ParserPtr subnet_parser;
ParserPtr iface_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
......@@ -646,6 +644,13 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
continue;
}
if (config_pair.first == "client-classes") {
ClientClassDefListParser parser;
parser.parse(config_pair.second, AF_INET);
continue;
}
ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
......@@ -665,8 +670,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
// but defer the commit until everything else has committed.
hooks_parser = parser;
parser->build(config_pair.second);
} 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.
......@@ -679,15 +682,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
......@@ -1164,8 +1164,8 @@ namespace isc { namespace dhcp {
enum
{
yyeof_ = 0,
yylast_ = 630, ///< Last index in yytable_.
yynnts_ = 271, ///< Number of nonterminal symbols.
yylast_ = 638, ///< Last index in yytable_.
yynnts_ = 273, ///< Number of nonterminal symbols.
yyfinal_ = 24, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
......@@ -2129,9 +2129,9 @@ namespace isc { namespace dhcp {
}
#line 14 "dhcp6_parser.yy" // lalr1.cc:377
#line 14 "dhcp6_parser.yy" // lalr1.cc:392
} } // isc::dhcp
#line 2135 "dhcp6_parser.h" // lalr1.cc:377
#line 2135 "dhcp6_parser.h" // lalr1.cc:392
......
/* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
/* Copyright (C) 2016-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
......@@ -261,14 +261,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
;
......@@ -283,6 +275,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 -----------------------------
......@@ -425,7 +439,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();
};
......@@ -571,12 +585,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();
};
......@@ -1192,7 +1208,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();
};
......@@ -1202,7 +1218,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();
};
......@@ -1236,7 +1252,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();
};
......
......@@ -722,8 +722,7 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
// control-socket has been converted to SimpleParser.
} else if (config_id.compare("expired-leases-processing") == 0) {
parser = new ExpirationConfigParser();
} else if (config_id.compare("client-classes") == 0) {
parser = new ClientClassDefListParser(config_id, globalContext());
// client-classes has been converted to SimpleParser.
} else if (config_id.compare("server-id") == 0) {
parser = new DUIDConfigParser();
// host-reservation-identifiers have been converted to SimpleParser already.
......@@ -845,7 +844,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
ParserPtr subnet_parser;
ParserPtr iface_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
......@@ -925,6 +923,12 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
continue;
}
if (config_pair.first =="client-classes") {
ClientClassDefListParser parser;
parser.parse(config_pair.second, AF_INET6);
continue;
}
ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
......@@ -945,8 +949,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
// can be run here before other parsers.
parser->build(config_pair.second);
iface_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.
......@@ -959,15 +961,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,12 @@ namespace dhcp {
// ********************** ExpressionParser ****************************
ExpressionParser::ExpressionParser(const std::string&,
ExpressionPtr& expression, ParserContextPtr global_context)
: local_expression_(ExpressionPtr()), expression_(expression),
global_context_(global_context) {
ExpressionParser::ExpressionParser(ExpressionPtr& expression)
: local_expression_(ExpressionPtr()), expression_(expression) {
}
void
ExpressionParser::build(ConstElementPtr expression_cfg) {
ExpressionParser::parse(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,7 +45,7 @@ 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;
......@@ -57,76 +56,63 @@ ExpressionParser::build(ConstElementPtr expression_cfg) {
<< "] error: " << ex.what() << " at ("
<< expression_cfg->getPosition() << ")");
}
}
void
ExpressionParser::commit() {
// Success so commit.
expression_ = local_expression_;
}
// ********************** ClientClassDefParser ****************************
ClientClassDefParser::ClientClassDefParser(const std::string&,
ClientClassDictionaryPtr& class_dictionary, ParserContextPtr global_context)
: string_values_(new StringStorage()),
match_expr_(ExpressionPtr()),
ClientClassDefParser::ClientClassDefParser(ClientClassDictionaryPtr& class_dictionary)
: match_expr_(ExpressionPtr()),
options_(new CfgOption()),
class_dictionary_(class_dictionary),
global_context_(global_context) {
class_dictionary_(class_dictionary) {
}
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(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;
// 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(match_expr_);
parser.parse(value, family);
} else if (entry == "option-data") {
OptionDataListParser opts_parser(family);
opts_parser.parse(options_, value);
} else if (entry == "next-server") {
next_server_txt = value->stringValue();
} else if (entry == "server-hostname") {
sname = value->stringValue();
} else if (entry == "boot-file-name") {
filename = value->stringValue();
} else {
isc_throw(DhcpConfigError, "invalid parameter '" << entry
<< "' (" << value->getPosition() << ")");
}
}
// Make name mandatory?
// Let's parse the next-server field
IOAddress next_server("0.0.0.0");
string next_server_txt = string_values_->getOptionalParam("next-server", "0.0.0.0");
try {
next_server = IOAddress(next_server_txt);
} catch (const IOError& ex) {
......@@ -144,22 +130,21 @@ ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
<< next_server_txt << "', must not be a broadcast");
}
// Let's try to parse sname
string sname = string_values_->getOptionalParam("server-hostname", "");
// Let's try to parse server-hostname
if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
isc_throw(DhcpConfigError, "server-hostname must be at most "
<< Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
<< sname.length());
}
string filename = string_values_->getOptionalParam("boot-file-name", "");
// Let's try to parse boot-file-name
if (filename.length() > Pkt4::MAX_FILE_LEN) {
isc_throw(DhcpConfigError, "boot-file-name must be at most "
<< Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
<< filename.length());
}
// an OptionCollectionPtr
// Add the client class definition
class_dictionary_->addClass(name, match_expr_, options_, next_server,
sname, filename);
} catch (const std::exception& ex) {
......@@ -170,33 +155,19 @@ ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
// ****************** ClientClassDefListParser ************************
ClientClassDefListParser::ClientClassDefListParser(const std::string&,
ParserContextPtr
global_context)
: local_dictionary_(new ClientClassDictionary()),
global_context_(global_context) {
ClientClassDefListParser::ClientClassDefListParser()
: local_dictionary_(new ClientClassDictionary()) {
}
void
ClientClassDefListParser::build(ConstElementPtr client_class_def_list) {
if (!client_class_def_list) {
isc_throw(DhcpConfigError, "parser error: a pointer to a list of"
<< " client class definitions is NULL ("
<< client_class_def_list->getPosition() << ")");
}
ClientClassDefListParser::parse(ConstElementPtr client_class_def_list,
uint16_t family) {
BOOST_FOREACH(ConstElementPtr client_class_def,
client_class_def_list->listValue()) {
boost::shared_ptr<ClientClassDefParser>
parser(new ClientClassDefParser("client-class-def",
local_dictionary_,
global_context_));
parser->build(client_class_def);
ClientClassDefParser parser(local_dictionary_);
parser.parse(client_class_def, family);
}
}
void
ClientClassDefListParser::commit() {
// Success so commit
CfgMgr::instance().getStagingCfg()->setClientClassDictionary(local_dictionary_);
}
......
// Copyright (C) 2015 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
......@@ -7,10 +7,11 @@