2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 05:55:28 +00:00

[master] Merge branch 'trac5020' (interfaces parser migrated to SimpleParser)

# Conflicts:
#	src/bin/dhcp4/json_config_parser.cc
#	src/bin/dhcp6/json_config_parser.cc
This commit is contained in:
Tomek Mrugalski
2017-01-10 14:48:57 +01:00
15 changed files with 2114 additions and 2139 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* 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
@@ -196,6 +196,24 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence}
}
}
\"raw\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP_SOCKET_TYPE:
return isc::dhcp::Dhcp4Parser::make_RAW(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("raw", driver.loc_);
}
}
\"udp\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP_SOCKET_TYPE:
return isc::dhcp::Dhcp4Parser::make_UDP(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("udp", driver.loc_);
}
}
\"interfaces\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::INTERFACES_CONFIG:

File diff suppressed because it is too large Load Diff

View File

@@ -305,6 +305,7 @@ namespace isc { namespace dhcp {
union union_type
{
// value
// socket_type
char dummy1[sizeof(ElementPtr)];
// "boolean"
@@ -352,94 +353,96 @@ namespace isc { namespace dhcp {
TOKEN_INTERFACES_CONFIG = 266,
TOKEN_INTERFACES = 267,
TOKEN_DHCP_SOCKET_TYPE = 268,
TOKEN_ECHO_CLIENT_ID = 269,
TOKEN_MATCH_CLIENT_ID = 270,
TOKEN_NEXT_SERVER = 271,
TOKEN_SERVER_HOSTNAME = 272,
TOKEN_BOOT_FILE_NAME = 273,
TOKEN_LEASE_DATABASE = 274,
TOKEN_HOSTS_DATABASE = 275,
TOKEN_TYPE = 276,
TOKEN_USER = 277,
TOKEN_PASSWORD = 278,
TOKEN_HOST = 279,
TOKEN_PERSIST = 280,
TOKEN_LFC_INTERVAL = 281,
TOKEN_READONLY = 282,
TOKEN_VALID_LIFETIME = 283,
TOKEN_RENEW_TIMER = 284,
TOKEN_REBIND_TIMER = 285,
TOKEN_DECLINE_PROBATION_PERIOD = 286,
TOKEN_SUBNET4 = 287,
TOKEN_SUBNET_4O6_INTERFACE = 288,
TOKEN_SUBNET_4O6_INTERFACE_ID = 289,
TOKEN_SUBNET_4O6_SUBNET = 290,
TOKEN_OPTION_DEF = 291,
TOKEN_OPTION_DATA = 292,
TOKEN_NAME = 293,
TOKEN_DATA = 294,
TOKEN_CODE = 295,
TOKEN_SPACE = 296,
TOKEN_CSV_FORMAT = 297,
TOKEN_RECORD_TYPES = 298,
TOKEN_ENCAPSULATE = 299,
TOKEN_ARRAY = 300,
TOKEN_POOLS = 301,
TOKEN_POOL = 302,
TOKEN_SUBNET = 303,
TOKEN_INTERFACE = 304,
TOKEN_INTERFACE_ID = 305,
TOKEN_ID = 306,
TOKEN_RAPID_COMMIT = 307,
TOKEN_RESERVATION_MODE = 308,
TOKEN_HOST_RESERVATION_IDENTIFIERS = 309,
TOKEN_CLIENT_CLASSES = 310,
TOKEN_TEST = 311,
TOKEN_CLIENT_CLASS = 312,
TOKEN_RESERVATIONS = 313,
TOKEN_DUID = 314,
TOKEN_HW_ADDRESS = 315,
TOKEN_CIRCUIT_ID = 316,
TOKEN_CLIENT_ID = 317,
TOKEN_HOSTNAME = 318,
TOKEN_RELAY = 319,
TOKEN_IP_ADDRESS = 320,
TOKEN_HOOKS_LIBRARIES = 321,
TOKEN_LIBRARY = 322,
TOKEN_PARAMETERS = 323,
TOKEN_EXPIRED_LEASES_PROCESSING = 324,
TOKEN_SERVER_ID = 325,
TOKEN_IDENTIFIER = 326,
TOKEN_HTYPE = 327,
TOKEN_TIME = 328,
TOKEN_ENTERPRISE_ID = 329,
TOKEN_DHCP4O6_PORT = 330,
TOKEN_CONTROL_SOCKET = 331,
TOKEN_SOCKET_TYPE = 332,
TOKEN_SOCKET_NAME = 333,
TOKEN_DHCP_DDNS = 334,
TOKEN_LOGGING = 335,
TOKEN_LOGGERS = 336,
TOKEN_OUTPUT_OPTIONS = 337,
TOKEN_OUTPUT = 338,
TOKEN_DEBUGLEVEL = 339,
TOKEN_SEVERITY = 340,
TOKEN_DHCP6 = 341,
TOKEN_DHCPDDNS = 342,
TOKEN_TOPLEVEL_JSON = 343,
TOKEN_TOPLEVEL_DHCP4 = 344,
TOKEN_SUB_DHCP4 = 345,
TOKEN_SUB_INTERFACES4 = 346,
TOKEN_SUB_SUBNET4 = 347,
TOKEN_SUB_POOL4 = 348,
TOKEN_SUB_RESERVATION = 349,
TOKEN_SUB_OPTION_DEF = 350,
TOKEN_SUB_OPTION_DATA = 351,
TOKEN_SUB_HOOKS_LIBRARY = 352,
TOKEN_STRING = 353,
TOKEN_INTEGER = 354,
TOKEN_FLOAT = 355,
TOKEN_BOOLEAN = 356
TOKEN_RAW = 269,
TOKEN_UDP = 270,
TOKEN_ECHO_CLIENT_ID = 271,
TOKEN_MATCH_CLIENT_ID = 272,
TOKEN_NEXT_SERVER = 273,
TOKEN_SERVER_HOSTNAME = 274,
TOKEN_BOOT_FILE_NAME = 275,
TOKEN_LEASE_DATABASE = 276,
TOKEN_HOSTS_DATABASE = 277,
TOKEN_TYPE = 278,
TOKEN_USER = 279,
TOKEN_PASSWORD = 280,
TOKEN_HOST = 281,
TOKEN_PERSIST = 282,
TOKEN_LFC_INTERVAL = 283,
TOKEN_READONLY = 284,
TOKEN_VALID_LIFETIME = 285,
TOKEN_RENEW_TIMER = 286,
TOKEN_REBIND_TIMER = 287,
TOKEN_DECLINE_PROBATION_PERIOD = 288,
TOKEN_SUBNET4 = 289,
TOKEN_SUBNET_4O6_INTERFACE = 290,
TOKEN_SUBNET_4O6_INTERFACE_ID = 291,
TOKEN_SUBNET_4O6_SUBNET = 292,
TOKEN_OPTION_DEF = 293,
TOKEN_OPTION_DATA = 294,
TOKEN_NAME = 295,
TOKEN_DATA = 296,
TOKEN_CODE = 297,
TOKEN_SPACE = 298,
TOKEN_CSV_FORMAT = 299,
TOKEN_RECORD_TYPES = 300,
TOKEN_ENCAPSULATE = 301,
TOKEN_ARRAY = 302,
TOKEN_POOLS = 303,
TOKEN_POOL = 304,
TOKEN_SUBNET = 305,
TOKEN_INTERFACE = 306,
TOKEN_INTERFACE_ID = 307,
TOKEN_ID = 308,
TOKEN_RAPID_COMMIT = 309,
TOKEN_RESERVATION_MODE = 310,
TOKEN_HOST_RESERVATION_IDENTIFIERS = 311,
TOKEN_CLIENT_CLASSES = 312,
TOKEN_TEST = 313,
TOKEN_CLIENT_CLASS = 314,
TOKEN_RESERVATIONS = 315,
TOKEN_DUID = 316,
TOKEN_HW_ADDRESS = 317,
TOKEN_CIRCUIT_ID = 318,
TOKEN_CLIENT_ID = 319,
TOKEN_HOSTNAME = 320,
TOKEN_RELAY = 321,
TOKEN_IP_ADDRESS = 322,
TOKEN_HOOKS_LIBRARIES = 323,
TOKEN_LIBRARY = 324,
TOKEN_PARAMETERS = 325,
TOKEN_EXPIRED_LEASES_PROCESSING = 326,
TOKEN_SERVER_ID = 327,
TOKEN_IDENTIFIER = 328,
TOKEN_HTYPE = 329,
TOKEN_TIME = 330,
TOKEN_ENTERPRISE_ID = 331,
TOKEN_DHCP4O6_PORT = 332,
TOKEN_CONTROL_SOCKET = 333,
TOKEN_SOCKET_TYPE = 334,
TOKEN_SOCKET_NAME = 335,
TOKEN_DHCP_DDNS = 336,
TOKEN_LOGGING = 337,
TOKEN_LOGGERS = 338,
TOKEN_OUTPUT_OPTIONS = 339,
TOKEN_OUTPUT = 340,
TOKEN_DEBUGLEVEL = 341,
TOKEN_SEVERITY = 342,
TOKEN_DHCP6 = 343,
TOKEN_DHCPDDNS = 344,
TOKEN_TOPLEVEL_JSON = 345,
TOKEN_TOPLEVEL_DHCP4 = 346,
TOKEN_SUB_DHCP4 = 347,
TOKEN_SUB_INTERFACES4 = 348,
TOKEN_SUB_SUBNET4 = 349,
TOKEN_SUB_POOL4 = 350,
TOKEN_SUB_RESERVATION = 351,
TOKEN_SUB_OPTION_DEF = 352,
TOKEN_SUB_OPTION_DATA = 353,
TOKEN_SUB_HOOKS_LIBRARY = 354,
TOKEN_STRING = 355,
TOKEN_INTEGER = 356,
TOKEN_FLOAT = 357,
TOKEN_BOOLEAN = 358
};
};
@@ -602,6 +605,14 @@ namespace isc { namespace dhcp {
symbol_type
make_DHCP_SOCKET_TYPE (const location_type& l);
static inline
symbol_type
make_RAW (const location_type& l);
static inline
symbol_type
make_UDP (const location_type& l);
static inline
symbol_type
make_ECHO_CLIENT_ID (const location_type& l);
@@ -1159,12 +1170,12 @@ namespace isc { namespace dhcp {
enum
{
yyeof_ = 0,
yylast_ = 624, ///< Last index in yytable_.
yynnts_ = 267, ///< Number of nonterminal symbols.
yylast_ = 626, ///< Last index in yytable_.
yynnts_ = 268, ///< Number of nonterminal symbols.
yyfinal_ = 22, ///< Termination state number.
yyterror_ = 1,
yyerrcode_ = 256,
yyntokens_ = 102 ///< Number of tokens.
yyntokens_ = 104 ///< Number of tokens.
};
@@ -1216,9 +1227,9 @@ namespace isc { namespace dhcp {
65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99, 100, 101
95, 96, 97, 98, 99, 100, 101, 102, 103
};
const unsigned int user_token_number_max_ = 356;
const unsigned int user_token_number_max_ = 358;
const token_number_type undef_token_ = 2;
if (static_cast<int>(t) <= yyeof_)
@@ -1251,23 +1262,24 @@ namespace isc { namespace dhcp {
{
switch (other.type_get ())
{
case 114: // value
case 116: // value
case 155: // socket_type
value.copy< ElementPtr > (other.value);
break;
case 101: // "boolean"
case 103: // "boolean"
value.copy< bool > (other.value);
break;
case 100: // "floating point"
case 102: // "floating point"
value.copy< double > (other.value);
break;
case 99: // "integer"
case 101: // "integer"
value.copy< int64_t > (other.value);
break;
case 98: // "constant string"
case 100: // "constant string"
value.copy< std::string > (other.value);
break;
@@ -1288,23 +1300,24 @@ namespace isc { namespace dhcp {
(void) v;
switch (this->type_get ())
{
case 114: // value
case 116: // value
case 155: // socket_type
value.copy< ElementPtr > (v);
break;
case 101: // "boolean"
case 103: // "boolean"
value.copy< bool > (v);
break;
case 100: // "floating point"
case 102: // "floating point"
value.copy< double > (v);
break;
case 99: // "integer"
case 101: // "integer"
value.copy< int64_t > (v);
break;
case 98: // "constant string"
case 100: // "constant string"
value.copy< std::string > (v);
break;
@@ -1384,23 +1397,24 @@ namespace isc { namespace dhcp {
// Type destructor.
switch (yytype)
{
case 114: // value
case 116: // value
case 155: // socket_type
value.template destroy< ElementPtr > ();
break;
case 101: // "boolean"
case 103: // "boolean"
value.template destroy< bool > ();
break;
case 100: // "floating point"
case 102: // "floating point"
value.template destroy< double > ();
break;
case 99: // "integer"
case 101: // "integer"
value.template destroy< int64_t > ();
break;
case 98: // "constant string"
case 100: // "constant string"
value.template destroy< std::string > ();
break;
@@ -1427,23 +1441,24 @@ namespace isc { namespace dhcp {
super_type::move(s);
switch (this->type_get ())
{
case 114: // value
case 116: // value
case 155: // socket_type
value.move< ElementPtr > (s.value);
break;
case 101: // "boolean"
case 103: // "boolean"
value.move< bool > (s.value);
break;
case 100: // "floating point"
case 102: // "floating point"
value.move< double > (s.value);
break;
case 99: // "integer"
case 101: // "integer"
value.move< int64_t > (s.value);
break;
case 98: // "constant string"
case 100: // "constant string"
value.move< std::string > (s.value);
break;
@@ -1512,7 +1527,7 @@ namespace isc { namespace dhcp {
325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
355, 356
355, 356, 357, 358
};
return static_cast<token_type> (yytoken_number_[type]);
}
@@ -1589,6 +1604,18 @@ namespace isc { namespace dhcp {
return symbol_type (token::TOKEN_DHCP_SOCKET_TYPE, l);
}
Dhcp4Parser::symbol_type
Dhcp4Parser::make_RAW (const location_type& l)
{
return symbol_type (token::TOKEN_RAW, l);
}
Dhcp4Parser::symbol_type
Dhcp4Parser::make_UDP (const location_type& l)
{
return symbol_type (token::TOKEN_UDP, l);
}
Dhcp4Parser::symbol_type
Dhcp4Parser::make_ECHO_CLIENT_ID (const location_type& l)
{
@@ -2120,7 +2147,7 @@ namespace isc { namespace dhcp {
#line 14 "dhcp4_parser.yy" // lalr1.cc:377
} } // isc::dhcp
#line 2124 "dhcp4_parser.h" // lalr1.cc:377
#line 2151 "dhcp4_parser.h" // lalr1.cc:377

View File

@@ -1,4 +1,4 @@
/* 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
@@ -53,6 +53,8 @@ using namespace std;
INTERFACES_CONFIG "interfaces-config"
INTERFACES "interfaces"
DHCP_SOCKET_TYPE "dhcp-socket-type"
RAW "raw"
UDP "udp"
ECHO_CLIENT_ID "echo-client-id"
MATCH_CLIENT_ID "match-client-id"
@@ -185,6 +187,7 @@ using namespace std;
%token <bool> BOOLEAN "boolean"
%type <ElementPtr> value
%type <ElementPtr> socket_type
%printer { yyoutput << $$; } <*>;
@@ -444,13 +447,16 @@ interfaces_list: INTERFACES {
};
dhcp_socket_type: DHCP_SOCKET_TYPE {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr type(new StringElement($4, ctx.loc2pos(@4)));
ctx.stack_.back()->set("dhcp-socket-type", type);
ctx.enter(ctx.DHCP_SOCKET_TYPE);
} COLON socket_type {
ctx.stack_.back()->set("dhcp-socket-type", $4);
ctx.leave();
};
socket_type: RAW { $$ = ElementPtr(new StringElement("raw", ctx.loc2pos(@1))); }
| UDP { $$ = ElementPtr(new StringElement("udp", ctx.loc2pos(@1))); }
;
lease_database: LEASE_DATABASE {
ElementPtr i(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("lease-database", i);
@@ -1363,11 +1369,11 @@ control_socket_params: control_socket_param
| control_socket_params COMMA control_socket_param
;
control_socket_param: socket_type
| socket_name
control_socket_param: control_socket_type
| control_socket_name
;
socket_type: SOCKET_TYPE {
control_socket_type: SOCKET_TYPE {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr stype(new StringElement($4, ctx.loc2pos(@4)));
@@ -1375,7 +1381,7 @@ socket_type: SOCKET_TYPE {
ctx.leave();
};
socket_name: SOCKET_NAME {
control_socket_name: SOCKET_NAME {
ctx.enter(ctx.NO_KEYWORD);
} COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));

View File

@@ -418,10 +418,9 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
(config_id.compare("dhcp4o6-port") == 0) ) {
parser = new Uint32Parser(config_id,
globalContext()->uint32_values_);
} else if (config_id.compare("interfaces-config") == 0) {
parser = new IfacesConfigParser4();
} else if (config_id.compare("subnet4") == 0) {
parser = new Subnets4ListConfigParser(config_id);
// interface-config has been migrated to SimpleParser already.
// option-data and option-def have been converted to SimpleParser already.
} else if ((config_id.compare("next-server") == 0)) {
parser = new StringParser(config_id,
@@ -571,7 +570,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
// Please do not change this order!
ParserCollection independent_parsers;
ParserPtr subnet_parser;
ParserPtr iface_parser;
ParserPtr leases_parser;
ParserPtr client_classes_parser;
@@ -620,6 +618,11 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
const std::map<std::string, ConstElementPtr>& values_map =
mutable_cfg->mapValue();
BOOST_FOREACH(config_pair, values_map) {
// In principle we could have the following code structured as a series
// of long if else if clauses. That would give a marginal performance
// boost, but would make the code less readable. We had serious issues
// with the parser code debugability, so I decided to keep it as a
// series of independent ifs.
if (config_pair.first == "option-def") {
// This is converted to SimpleParser and is handled already above.
@@ -646,6 +649,14 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
continue;
}
if (config_pair.first == "interfaces-config") {
IfacesConfigParser parser(AF_INET);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
parser.parse(cfg_iface, config_pair.second);
continue;
}
// Legacy DhcpConfigParser stuff below
ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
@@ -654,11 +665,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 == "interfaces-config") {
// The interface parser is independent from any other
// parser and can be run here before any other parsers.
iface_parser = parser;
parser->build(config_pair.second);
} else if (config_pair.first == "hooks-libraries") {
// Executing commit will alter currently-loaded hooks
// libraries. Check if the supplied libraries are valid,

View File

@@ -1,4 +1,4 @@
// Generated 201612201711
// Generated 201701062338
// A Bison parser, made by GNU Bison 3.0.4.
// Locations for Bison parsers in C++

View File

@@ -127,6 +127,8 @@ Parser4Context::contextName()
return ("Logging");
case INTERFACES_CONFIG:
return ("interfaces-config");
case DHCP_SOCKET_TYPE:
return ("dhcp-socket-type");
case LEASE_DATABASE:
return ("lease-database");
case HOSTS_DATABASE:

View File

@@ -1,4 +1,4 @@
// 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
@@ -193,6 +193,9 @@ public:
/// Used while parsing Dhcp4/interfaces structures.
INTERFACES_CONFIG,
/// Used while parsing Dhcp4/interfaces/dhcp-socket-type structures.
DHCP_SOCKET_TYPE,
/// Used while parsing Dhcp4/lease-database structures.
LEASE_DATABASE,

View File

@@ -1,4 +1,4 @@
// Generated 201612201711
// Generated 201701062338
// A Bison parser, made by GNU Bison 3.0.4.
// Positions for Bison parsers in C++

View File

@@ -1,4 +1,4 @@
// Generated 201612201711
// Generated 201701062338
// A Bison parser, made by GNU Bison 3.0.4.
// Stack handling for Bison parsers in C++

View File

@@ -699,15 +699,12 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
(config_id.compare("dhcp4o6-port") == 0) ) {
parser = new Uint32Parser(config_id,
globalContext()->uint32_values_);
} else if (config_id.compare("interfaces-config") == 0) {
parser = new IfacesConfigParser6();
} else if (config_id.compare("subnet6") == 0) {
parser = new Subnets6ListConfigParser(config_id);
// option-data and option-def are no longer needed here. They're now
// converted to SimpleParser and are handled in configureDhcp6Server
} else if (config_id.compare("version") == 0) {
parser = new StringParser(config_id,
globalContext()->string_values_);
// converted to SimpleParser and are handled in configureDhcp6Server.
// interfaces-config has been converted to SimpleParser.
// version was removed - it was a leftover from bindctrl.
} else if (config_id.compare("lease-database") == 0) {
parser = new DbAccessParser(config_id, DbAccessParser::LEASE_DB);
} else if (config_id.compare("hosts-database") == 0) {
@@ -842,7 +839,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
// Please do not change this order!
ParserCollection independent_parsers;
ParserPtr subnet_parser;
ParserPtr iface_parser;
ParserPtr leases_parser;
ParserPtr client_classes_parser;
@@ -891,6 +887,11 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
}
BOOST_FOREACH(config_pair, values_map) {
// In principle we could have the following code structured as a series
// of long if else if clauses. That would give a marginal performance
// boost, but would make the code less readable. We had serious issues
// with the parser code debugability, so I decided to keep it as a
// series of independent ifs.
if (config_pair.first == "option-def") {
// This is converted to SimpleParser and is handled already above.
@@ -931,6 +932,13 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
continue;
}
if (config_pair.first == "interfaces-config") {
IfacesConfigParser parser(AF_INET6);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
parser.parse(cfg_iface, config_pair.second);
continue;
}
ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
config_pair.second));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
@@ -946,11 +954,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
// committed.
hooks_parser = parser;
hooks_parser->build(config_pair.second);
} else if (config_pair.first == "interfaces-config") {
// The interface parser is independent from any other parser and
// 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 {

View File

@@ -18,82 +18,56 @@ using namespace isc::data;
namespace isc {
namespace dhcp {
InterfaceListConfigParser::InterfaceListConfigParser(const uint16_t protocol)
: protocol_(protocol) {
}
void
InterfaceListConfigParser::build(ConstElementPtr value) {
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
IfacesConfigParser::parseInterfacesList(const CfgIfacePtr& cfg_iface,
ConstElementPtr ifaces_list) {
BOOST_FOREACH(ConstElementPtr iface, ifaces_list->listValue()) {
std::string iface_name = iface->stringValue();
try {
cfg_iface->use(protocol_, iface_name);
} catch (const std::exception& ex) {
isc_throw(DhcpConfigError, "Failed to select interface: "
<< ex.what() << " (" << value->getPosition() << ")");
<< ex.what() << " (" << iface->getPosition() << ")");
}
}
}
void
InterfaceListConfigParser::commit() {
// Nothing to do.
}
IfacesConfigParser::IfacesConfigParser(const uint16_t protocol)
: protocol_(protocol) {
}
void
IfacesConfigParser::build(isc::data::ConstElementPtr ifaces_config) {
BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
try {
if (element.first == "interfaces") {
InterfaceListConfigParser parser(protocol_);
parser.build(element.second);
}
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
<< element.second->getPosition() << ")");
}
}
}
bool
IfacesConfigParser::isGenericParameter(const std::string& parameter) const {
// Currently, the "interfaces" is the only common parameter for
// DHCPv4 and DHCPv6.
return (parameter == "interfaces");
}
IfacesConfigParser4::IfacesConfigParser4()
: IfacesConfigParser(AF_INET) {
}
void
IfacesConfigParser4::build(isc::data::ConstElementPtr ifaces_config) {
IfacesConfigParser::build(ifaces_config);
IfacesConfigParser::parse(const CfgIfacePtr& cfg,
const isc::data::ConstElementPtr& ifaces_config) {
// Get the pointer to the interface configuration.
CfgIfacePtr cfg = CfgMgr::instance().getStagingCfg()->getCfgIface();
bool socket_type_specified = false;
BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
try {
if (element.first == "dhcp-socket-type") {
cfg->useSocketType(AF_INET, element.second->stringValue());
socket_type_specified = true;
if (element.first == "interfaces") {
parseInterfacesList(cfg, element.second);
continue;
} else if (!isGenericParameter(element.first)) {
isc_throw(DhcpConfigError, "usupported parameter '"
<< element.first << "'");
}
if (element.first == "dhcp-socket-type") {
if (protocol_ == AF_INET) {
cfg->useSocketType(AF_INET, element.second->stringValue());
socket_type_specified = true;
continue;
} else {
isc_throw(DhcpConfigError,
"dhcp-socket-type is not supported in DHCPv6");
}
}
// This should never happen as the input produced by the parser
// see (src/bin/dhcpX/dhcpX_parser.yy) should not produce any
// other parameter, so this case is only to catch bugs in
// the parser.
isc_throw(DhcpConfigError, "unsupported parameter '"
<< element.first << "'");
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
@@ -102,35 +76,13 @@ IfacesConfigParser4::build(isc::data::ConstElementPtr ifaces_config) {
}
// User hasn't specified the socket type. Log that we are using
// the default type.
if (!socket_type_specified) {
// the default type. Log it only if this is DHCPv4. (DHCPv6 does not use
// raw sockets).
if (!socket_type_specified && (protocol_ == AF_INET) ) {
LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_SOCKET_TYPE_DEFAULT)
.arg(cfg->socketTypeToText());
}
}
IfacesConfigParser6::IfacesConfigParser6()
: IfacesConfigParser(AF_INET6) {
}
void
IfacesConfigParser6::build(isc::data::ConstElementPtr ifaces_config) {
IfacesConfigParser::build(ifaces_config);
BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
try {
if (!isGenericParameter(element.first)) {
isc_throw(DhcpConfigError, "usupported parameter '"
<< element.first << "'");
}
} catch (const std::exception& ex) {
// Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " ("
<< element.second->getPosition() << ")");
}
}
}
} // end of namespace isc::dhcp
} // end of namespace isc

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2015-2016 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
@@ -8,65 +8,22 @@
#define IFACES_CONFIG_PARSER_H
#include <cc/data.h>
#include <dhcpsrv/parsers/dhcp_config_parser.h>
#include <cc/simple_parser.h>
#include <dhcpsrv/cfg_iface.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
namespace isc {
namespace dhcp {
/// @brief Parser for interface list definition.
///
/// This parser handles Dhcp4/interfaces-config/interfaces and
/// Dhcp6/interfaces-config/interfaces entries.
/// It contains a list of network interfaces that the server listens on.
/// In particular, it can contain an "*" that designates all interfaces.
class InterfaceListConfigParser : public DhcpConfigParser {
public:
/// @brief Constructor
///
/// @param protocol AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
InterfaceListConfigParser(const uint16_t protocol);
/// @brief Parses a list of interface names.
///
/// This method parses a list of interface/address tuples in a text
/// format. The tuples specify the IP addresses and corresponding
/// interface names on which the server should listen to the DHCP
/// messages. The address is optional in each tuple and, if not
/// specified, the interface name (without slash character) should
/// be present.
///
/// @param value pointer to the content of parsed values
///
/// @throw DhcpConfigError if the interface names and/or addresses
/// are invalid.
virtual void build(isc::data::ConstElementPtr value);
/// @brief Does nothing.
virtual void commit();
private:
/// @brief AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
uint16_t protocol_;
};
/// @brief Parser for the configuration of interfaces.
///
/// This parser parses the "interfaces-config" parameter which holds the
/// full configuration of the DHCP server with respect to the use of
/// interfaces, sockets and alike.
/// interfaces, DHCP traffic sockets and alike.
///
/// This parser uses the @c InterfaceListConfigParser to parse the
/// list of interfaces on which the server should listen. It handles
/// remaining parameters internally.
///
/// This parser is used as a base for the DHCPv4 and DHCPv6 specific
/// parsers and should not be used directly.
class IfacesConfigParser : public DhcpConfigParser {
/// This parser is used in both DHCPv4 and DHCPv6. Derived parsers
/// are not needed.
class IfacesConfigParser : public isc::data::SimpleParser {
public:
/// @brief Constructor
@@ -74,81 +31,30 @@ public:
/// @param protocol AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
IfacesConfigParser(const uint16_t protocol);
/// @brief Parses generic parameters in "interfaces-config".
/// @brief Parses content of the "interfaces-config".
///
/// The generic parameters in the "interfaces-config" map are
/// the ones that are common for DHCPv4 and DHCPv6.
/// @param config parsed structures will be stored here
/// @param values pointer to the content of parsed values
///
/// @param ifaces_config A data element holding configuration of
/// interfaces.
virtual void build(isc::data::ConstElementPtr ifaces_config);
/// @brief Commit, unused.
virtual void commit() { }
/// @brief Checks if the specified parameter is a common parameter
/// for DHCPv4 and DHCPv6 interface configuration.
///
/// This method is invoked by the derived classes to check if the
/// particular parameter is supported.
///
/// @param parameter A name of the parameter.
///
/// @return true if the specified parameter is a common parameter
/// for DHCPv4 and DHCPv6 server.
bool isGenericParameter(const std::string& parameter) const;
/// @throw DhcpConfigError if the interface names and/or addresses
/// are invalid.
void parse(const CfgIfacePtr& config, const isc::data::ConstElementPtr& values);
private:
/// @brief parses interfaces-list structure
///
/// This method goes through all the interfaces-specified in
/// 'interfaces-list' and enabled them in the specified configuration
/// structure
///
/// @param cfg_iface parsed interfaces will be specified here
/// @param ifaces_list interfaces-list to be parsed
/// @throw DhcpConfigError if the interface names are invalid.
void parseInterfacesList(const CfgIfacePtr& cfg_iface,
isc::data::ConstElementPtr ifaces_list);
/// @brief AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
int protocol_;
};
/// @brief Parser for the "interfaces-config" parameter of the DHCPv4 server.
class IfacesConfigParser4 : public IfacesConfigParser {
public:
/// @brief Constructor.
///
/// Sets the protocol to AF_INET.
IfacesConfigParser4();
/// @brief Parses DHCPv4 specific parameters.
///
/// Internally it invokes the @c InterfaceConfigParser::build to parse
/// generic parameters. In addition, it parses the following parameters:
/// - dhcp-socket-type
///
/// @param ifaces_config A data element holding configuration of
/// interfaces.
///
/// @throw DhcpConfigError if unsupported parameters is specified.
virtual void build(isc::data::ConstElementPtr ifaces_config);
};
/// @brief Parser for the "interfaces-config" parameter of the DHCPv4 server.
class IfacesConfigParser6 : public IfacesConfigParser {
public:
/// @brief Constructor.
///
/// Sets the protocol to AF_INET6.
IfacesConfigParser6();
/// @brief Parses DHCPv6 specific parameters.
///
/// Internally it invokes the @c InterfaceConfigParser::build to parse
/// generic parameters. Currently it doesn't parse any other parameters.
///
/// @param ifaces_config A data element holding configuration of
/// interfaces.
///
/// @throw DhcpConfigError if unsupported parameters is specified.
virtual void build(isc::data::ConstElementPtr ifaces_config);
};
}

View File

@@ -56,8 +56,9 @@ TEST_F(IfacesConfigParserTest, interfaces) {
ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration.
IfacesConfigParser4 parser;
ASSERT_NO_THROW(parser.build(config_element));
IfacesConfigParser parser(AF_INET);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
// Open sockets according to the parsed configuration.
SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
@@ -77,7 +78,8 @@ TEST_F(IfacesConfigParserTest, interfaces) {
config = "{ \"interfaces\": [ \"eth0\", \"*\" ] }";
config_element = Element::fromJSON(config);
ASSERT_NO_THROW(parser.build(config_element));
cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
cfg = CfgMgr::instance().getStagingCfg();
ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000));
@@ -100,8 +102,9 @@ TEST_F(IfacesConfigParserTest, socketTypeRaw) {
ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration.
IfacesConfigParser4 parser;
ASSERT_NO_THROW(parser.build(config_element));
IfacesConfigParser parser(AF_INET);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
// Compare the resulting configuration with a reference
// configuration using the raw socket.
@@ -125,8 +128,9 @@ TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration.
IfacesConfigParser4 parser;
ASSERT_NO_THROW(parser.build(config_element));
IfacesConfigParser parser(AF_INET);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
// Compare the resulting configuration with a reference
// configuration using the raw socket.
@@ -139,18 +143,19 @@ TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
// Test that the configuration rejects the invalid socket type.
TEST_F(IfacesConfigParserTest, socketTypeInvalid) {
// For DHCPv4 we only accept the raw socket or datagram socket.
IfacesConfigParser4 parser4;
IfacesConfigParser parser4(AF_INET);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
std::string config = "{ \"interfaces\": [ ],"
"\"dhcp-socket-type\": \"default\" }";
ElementPtr config_element = Element::fromJSON(config);
ASSERT_THROW(parser4.build(config_element), DhcpConfigError);
ASSERT_THROW(parser4.parse(cfg_iface, config_element), DhcpConfigError);
// For DHCPv6 we don't accept any socket type.
IfacesConfigParser6 parser6;
IfacesConfigParser parser6(AF_INET6);
config = "{ \"interfaces\": [ ],"
" \"dhcp-socket-type\": \"udp\" }";
config_element = Element::fromJSON(config);
ASSERT_THROW(parser6.build(config_element), DhcpConfigError);
ASSERT_THROW(parser6.parse(cfg_iface, config_element), DhcpConfigError);
}
} // end of anonymous namespace