2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-01 22:45:18 +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 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 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\" { \"interfaces\" {
switch(driver.ctx_) { switch(driver.ctx_) {
case isc::dhcp::Parser4Context::INTERFACES_CONFIG: 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 union union_type
{ {
// value // value
// socket_type
char dummy1[sizeof(ElementPtr)]; char dummy1[sizeof(ElementPtr)];
// "boolean" // "boolean"
@@ -352,94 +353,96 @@ namespace isc { namespace dhcp {
TOKEN_INTERFACES_CONFIG = 266, TOKEN_INTERFACES_CONFIG = 266,
TOKEN_INTERFACES = 267, TOKEN_INTERFACES = 267,
TOKEN_DHCP_SOCKET_TYPE = 268, TOKEN_DHCP_SOCKET_TYPE = 268,
TOKEN_ECHO_CLIENT_ID = 269, TOKEN_RAW = 269,
TOKEN_MATCH_CLIENT_ID = 270, TOKEN_UDP = 270,
TOKEN_NEXT_SERVER = 271, TOKEN_ECHO_CLIENT_ID = 271,
TOKEN_SERVER_HOSTNAME = 272, TOKEN_MATCH_CLIENT_ID = 272,
TOKEN_BOOT_FILE_NAME = 273, TOKEN_NEXT_SERVER = 273,
TOKEN_LEASE_DATABASE = 274, TOKEN_SERVER_HOSTNAME = 274,
TOKEN_HOSTS_DATABASE = 275, TOKEN_BOOT_FILE_NAME = 275,
TOKEN_TYPE = 276, TOKEN_LEASE_DATABASE = 276,
TOKEN_USER = 277, TOKEN_HOSTS_DATABASE = 277,
TOKEN_PASSWORD = 278, TOKEN_TYPE = 278,
TOKEN_HOST = 279, TOKEN_USER = 279,
TOKEN_PERSIST = 280, TOKEN_PASSWORD = 280,
TOKEN_LFC_INTERVAL = 281, TOKEN_HOST = 281,
TOKEN_READONLY = 282, TOKEN_PERSIST = 282,
TOKEN_VALID_LIFETIME = 283, TOKEN_LFC_INTERVAL = 283,
TOKEN_RENEW_TIMER = 284, TOKEN_READONLY = 284,
TOKEN_REBIND_TIMER = 285, TOKEN_VALID_LIFETIME = 285,
TOKEN_DECLINE_PROBATION_PERIOD = 286, TOKEN_RENEW_TIMER = 286,
TOKEN_SUBNET4 = 287, TOKEN_REBIND_TIMER = 287,
TOKEN_SUBNET_4O6_INTERFACE = 288, TOKEN_DECLINE_PROBATION_PERIOD = 288,
TOKEN_SUBNET_4O6_INTERFACE_ID = 289, TOKEN_SUBNET4 = 289,
TOKEN_SUBNET_4O6_SUBNET = 290, TOKEN_SUBNET_4O6_INTERFACE = 290,
TOKEN_OPTION_DEF = 291, TOKEN_SUBNET_4O6_INTERFACE_ID = 291,
TOKEN_OPTION_DATA = 292, TOKEN_SUBNET_4O6_SUBNET = 292,
TOKEN_NAME = 293, TOKEN_OPTION_DEF = 293,
TOKEN_DATA = 294, TOKEN_OPTION_DATA = 294,
TOKEN_CODE = 295, TOKEN_NAME = 295,
TOKEN_SPACE = 296, TOKEN_DATA = 296,
TOKEN_CSV_FORMAT = 297, TOKEN_CODE = 297,
TOKEN_RECORD_TYPES = 298, TOKEN_SPACE = 298,
TOKEN_ENCAPSULATE = 299, TOKEN_CSV_FORMAT = 299,
TOKEN_ARRAY = 300, TOKEN_RECORD_TYPES = 300,
TOKEN_POOLS = 301, TOKEN_ENCAPSULATE = 301,
TOKEN_POOL = 302, TOKEN_ARRAY = 302,
TOKEN_SUBNET = 303, TOKEN_POOLS = 303,
TOKEN_INTERFACE = 304, TOKEN_POOL = 304,
TOKEN_INTERFACE_ID = 305, TOKEN_SUBNET = 305,
TOKEN_ID = 306, TOKEN_INTERFACE = 306,
TOKEN_RAPID_COMMIT = 307, TOKEN_INTERFACE_ID = 307,
TOKEN_RESERVATION_MODE = 308, TOKEN_ID = 308,
TOKEN_HOST_RESERVATION_IDENTIFIERS = 309, TOKEN_RAPID_COMMIT = 309,
TOKEN_CLIENT_CLASSES = 310, TOKEN_RESERVATION_MODE = 310,
TOKEN_TEST = 311, TOKEN_HOST_RESERVATION_IDENTIFIERS = 311,
TOKEN_CLIENT_CLASS = 312, TOKEN_CLIENT_CLASSES = 312,
TOKEN_RESERVATIONS = 313, TOKEN_TEST = 313,
TOKEN_DUID = 314, TOKEN_CLIENT_CLASS = 314,
TOKEN_HW_ADDRESS = 315, TOKEN_RESERVATIONS = 315,
TOKEN_CIRCUIT_ID = 316, TOKEN_DUID = 316,
TOKEN_CLIENT_ID = 317, TOKEN_HW_ADDRESS = 317,
TOKEN_HOSTNAME = 318, TOKEN_CIRCUIT_ID = 318,
TOKEN_RELAY = 319, TOKEN_CLIENT_ID = 319,
TOKEN_IP_ADDRESS = 320, TOKEN_HOSTNAME = 320,
TOKEN_HOOKS_LIBRARIES = 321, TOKEN_RELAY = 321,
TOKEN_LIBRARY = 322, TOKEN_IP_ADDRESS = 322,
TOKEN_PARAMETERS = 323, TOKEN_HOOKS_LIBRARIES = 323,
TOKEN_EXPIRED_LEASES_PROCESSING = 324, TOKEN_LIBRARY = 324,
TOKEN_SERVER_ID = 325, TOKEN_PARAMETERS = 325,
TOKEN_IDENTIFIER = 326, TOKEN_EXPIRED_LEASES_PROCESSING = 326,
TOKEN_HTYPE = 327, TOKEN_SERVER_ID = 327,
TOKEN_TIME = 328, TOKEN_IDENTIFIER = 328,
TOKEN_ENTERPRISE_ID = 329, TOKEN_HTYPE = 329,
TOKEN_DHCP4O6_PORT = 330, TOKEN_TIME = 330,
TOKEN_CONTROL_SOCKET = 331, TOKEN_ENTERPRISE_ID = 331,
TOKEN_SOCKET_TYPE = 332, TOKEN_DHCP4O6_PORT = 332,
TOKEN_SOCKET_NAME = 333, TOKEN_CONTROL_SOCKET = 333,
TOKEN_DHCP_DDNS = 334, TOKEN_SOCKET_TYPE = 334,
TOKEN_LOGGING = 335, TOKEN_SOCKET_NAME = 335,
TOKEN_LOGGERS = 336, TOKEN_DHCP_DDNS = 336,
TOKEN_OUTPUT_OPTIONS = 337, TOKEN_LOGGING = 337,
TOKEN_OUTPUT = 338, TOKEN_LOGGERS = 338,
TOKEN_DEBUGLEVEL = 339, TOKEN_OUTPUT_OPTIONS = 339,
TOKEN_SEVERITY = 340, TOKEN_OUTPUT = 340,
TOKEN_DHCP6 = 341, TOKEN_DEBUGLEVEL = 341,
TOKEN_DHCPDDNS = 342, TOKEN_SEVERITY = 342,
TOKEN_TOPLEVEL_JSON = 343, TOKEN_DHCP6 = 343,
TOKEN_TOPLEVEL_DHCP4 = 344, TOKEN_DHCPDDNS = 344,
TOKEN_SUB_DHCP4 = 345, TOKEN_TOPLEVEL_JSON = 345,
TOKEN_SUB_INTERFACES4 = 346, TOKEN_TOPLEVEL_DHCP4 = 346,
TOKEN_SUB_SUBNET4 = 347, TOKEN_SUB_DHCP4 = 347,
TOKEN_SUB_POOL4 = 348, TOKEN_SUB_INTERFACES4 = 348,
TOKEN_SUB_RESERVATION = 349, TOKEN_SUB_SUBNET4 = 349,
TOKEN_SUB_OPTION_DEF = 350, TOKEN_SUB_POOL4 = 350,
TOKEN_SUB_OPTION_DATA = 351, TOKEN_SUB_RESERVATION = 351,
TOKEN_SUB_HOOKS_LIBRARY = 352, TOKEN_SUB_OPTION_DEF = 352,
TOKEN_STRING = 353, TOKEN_SUB_OPTION_DATA = 353,
TOKEN_INTEGER = 354, TOKEN_SUB_HOOKS_LIBRARY = 354,
TOKEN_FLOAT = 355, TOKEN_STRING = 355,
TOKEN_BOOLEAN = 356 TOKEN_INTEGER = 356,
TOKEN_FLOAT = 357,
TOKEN_BOOLEAN = 358
}; };
}; };
@@ -602,6 +605,14 @@ namespace isc { namespace dhcp {
symbol_type symbol_type
make_DHCP_SOCKET_TYPE (const location_type& l); 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 static inline
symbol_type symbol_type
make_ECHO_CLIENT_ID (const location_type& l); make_ECHO_CLIENT_ID (const location_type& l);
@@ -1159,12 +1170,12 @@ namespace isc { namespace dhcp {
enum enum
{ {
yyeof_ = 0, yyeof_ = 0,
yylast_ = 624, ///< Last index in yytable_. yylast_ = 626, ///< Last index in yytable_.
yynnts_ = 267, ///< Number of nonterminal symbols. yynnts_ = 268, ///< Number of nonterminal symbols.
yyfinal_ = 22, ///< Termination state number. yyfinal_ = 22, ///< Termination state number.
yyterror_ = 1, yyterror_ = 1,
yyerrcode_ = 256, 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, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 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; const token_number_type undef_token_ = 2;
if (static_cast<int>(t) <= yyeof_) if (static_cast<int>(t) <= yyeof_)
@@ -1251,23 +1262,24 @@ namespace isc { namespace dhcp {
{ {
switch (other.type_get ()) switch (other.type_get ())
{ {
case 114: // value case 116: // value
case 155: // socket_type
value.copy< ElementPtr > (other.value); value.copy< ElementPtr > (other.value);
break; break;
case 101: // "boolean" case 103: // "boolean"
value.copy< bool > (other.value); value.copy< bool > (other.value);
break; break;
case 100: // "floating point" case 102: // "floating point"
value.copy< double > (other.value); value.copy< double > (other.value);
break; break;
case 99: // "integer" case 101: // "integer"
value.copy< int64_t > (other.value); value.copy< int64_t > (other.value);
break; break;
case 98: // "constant string" case 100: // "constant string"
value.copy< std::string > (other.value); value.copy< std::string > (other.value);
break; break;
@@ -1288,23 +1300,24 @@ namespace isc { namespace dhcp {
(void) v; (void) v;
switch (this->type_get ()) switch (this->type_get ())
{ {
case 114: // value case 116: // value
case 155: // socket_type
value.copy< ElementPtr > (v); value.copy< ElementPtr > (v);
break; break;
case 101: // "boolean" case 103: // "boolean"
value.copy< bool > (v); value.copy< bool > (v);
break; break;
case 100: // "floating point" case 102: // "floating point"
value.copy< double > (v); value.copy< double > (v);
break; break;
case 99: // "integer" case 101: // "integer"
value.copy< int64_t > (v); value.copy< int64_t > (v);
break; break;
case 98: // "constant string" case 100: // "constant string"
value.copy< std::string > (v); value.copy< std::string > (v);
break; break;
@@ -1384,23 +1397,24 @@ namespace isc { namespace dhcp {
// Type destructor. // Type destructor.
switch (yytype) switch (yytype)
{ {
case 114: // value case 116: // value
case 155: // socket_type
value.template destroy< ElementPtr > (); value.template destroy< ElementPtr > ();
break; break;
case 101: // "boolean" case 103: // "boolean"
value.template destroy< bool > (); value.template destroy< bool > ();
break; break;
case 100: // "floating point" case 102: // "floating point"
value.template destroy< double > (); value.template destroy< double > ();
break; break;
case 99: // "integer" case 101: // "integer"
value.template destroy< int64_t > (); value.template destroy< int64_t > ();
break; break;
case 98: // "constant string" case 100: // "constant string"
value.template destroy< std::string > (); value.template destroy< std::string > ();
break; break;
@@ -1427,23 +1441,24 @@ namespace isc { namespace dhcp {
super_type::move(s); super_type::move(s);
switch (this->type_get ()) switch (this->type_get ())
{ {
case 114: // value case 116: // value
case 155: // socket_type
value.move< ElementPtr > (s.value); value.move< ElementPtr > (s.value);
break; break;
case 101: // "boolean" case 103: // "boolean"
value.move< bool > (s.value); value.move< bool > (s.value);
break; break;
case 100: // "floating point" case 102: // "floating point"
value.move< double > (s.value); value.move< double > (s.value);
break; break;
case 99: // "integer" case 101: // "integer"
value.move< int64_t > (s.value); value.move< int64_t > (s.value);
break; break;
case 98: // "constant string" case 100: // "constant string"
value.move< std::string > (s.value); value.move< std::string > (s.value);
break; break;
@@ -1512,7 +1527,7 @@ namespace isc { namespace dhcp {
325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354,
355, 356 355, 356, 357, 358
}; };
return static_cast<token_type> (yytoken_number_[type]); 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); 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::symbol_type
Dhcp4Parser::make_ECHO_CLIENT_ID (const location_type& l) 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 #line 14 "dhcp4_parser.yy" // lalr1.cc:377
} } // isc::dhcp } } // 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 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 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_CONFIG "interfaces-config"
INTERFACES "interfaces" INTERFACES "interfaces"
DHCP_SOCKET_TYPE "dhcp-socket-type" DHCP_SOCKET_TYPE "dhcp-socket-type"
RAW "raw"
UDP "udp"
ECHO_CLIENT_ID "echo-client-id" ECHO_CLIENT_ID "echo-client-id"
MATCH_CLIENT_ID "match-client-id" MATCH_CLIENT_ID "match-client-id"
@@ -185,6 +187,7 @@ using namespace std;
%token <bool> BOOLEAN "boolean" %token <bool> BOOLEAN "boolean"
%type <ElementPtr> value %type <ElementPtr> value
%type <ElementPtr> socket_type
%printer { yyoutput << $$; } <*>; %printer { yyoutput << $$; } <*>;
@@ -444,13 +447,16 @@ interfaces_list: INTERFACES {
}; };
dhcp_socket_type: DHCP_SOCKET_TYPE { dhcp_socket_type: DHCP_SOCKET_TYPE {
ctx.enter(ctx.NO_KEYWORD); ctx.enter(ctx.DHCP_SOCKET_TYPE);
} COLON STRING { } COLON socket_type {
ElementPtr type(new StringElement($4, ctx.loc2pos(@4))); ctx.stack_.back()->set("dhcp-socket-type", $4);
ctx.stack_.back()->set("dhcp-socket-type", type);
ctx.leave(); ctx.leave();
}; };
socket_type: RAW { $$ = ElementPtr(new StringElement("raw", ctx.loc2pos(@1))); }
| UDP { $$ = ElementPtr(new StringElement("udp", ctx.loc2pos(@1))); }
;
lease_database: LEASE_DATABASE { lease_database: LEASE_DATABASE {
ElementPtr i(new MapElement(ctx.loc2pos(@1))); ElementPtr i(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("lease-database", i); 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_params COMMA control_socket_param
; ;
control_socket_param: socket_type control_socket_param: control_socket_type
| socket_name | control_socket_name
; ;
socket_type: SOCKET_TYPE { control_socket_type: SOCKET_TYPE {
ctx.enter(ctx.NO_KEYWORD); ctx.enter(ctx.NO_KEYWORD);
} COLON STRING { } COLON STRING {
ElementPtr stype(new StringElement($4, ctx.loc2pos(@4))); ElementPtr stype(new StringElement($4, ctx.loc2pos(@4)));
@@ -1375,7 +1381,7 @@ socket_type: SOCKET_TYPE {
ctx.leave(); ctx.leave();
}; };
socket_name: SOCKET_NAME { control_socket_name: SOCKET_NAME {
ctx.enter(ctx.NO_KEYWORD); ctx.enter(ctx.NO_KEYWORD);
} COLON STRING { } COLON STRING {
ElementPtr name(new StringElement($4, ctx.loc2pos(@4))); 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) ) { (config_id.compare("dhcp4o6-port") == 0) ) {
parser = new Uint32Parser(config_id, parser = new Uint32Parser(config_id,
globalContext()->uint32_values_); globalContext()->uint32_values_);
} else if (config_id.compare("interfaces-config") == 0) {
parser = new IfacesConfigParser4();
} else if (config_id.compare("subnet4") == 0) { } else if (config_id.compare("subnet4") == 0) {
parser = new Subnets4ListConfigParser(config_id); parser = new Subnets4ListConfigParser(config_id);
// interface-config has been migrated to SimpleParser already.
// option-data and option-def have been converted to SimpleParser already. // option-data and option-def have been converted to SimpleParser already.
} else if ((config_id.compare("next-server") == 0)) { } else if ((config_id.compare("next-server") == 0)) {
parser = new StringParser(config_id, parser = new StringParser(config_id,
@@ -571,7 +570,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
// Please do not change this order! // Please do not change this order!
ParserCollection independent_parsers; ParserCollection independent_parsers;
ParserPtr subnet_parser; ParserPtr subnet_parser;
ParserPtr iface_parser;
ParserPtr leases_parser; ParserPtr leases_parser;
ParserPtr client_classes_parser; ParserPtr client_classes_parser;
@@ -620,6 +618,11 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
const std::map<std::string, ConstElementPtr>& values_map = const std::map<std::string, ConstElementPtr>& values_map =
mutable_cfg->mapValue(); mutable_cfg->mapValue();
BOOST_FOREACH(config_pair, values_map) { 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") { if (config_pair.first == "option-def") {
// This is converted to SimpleParser and is handled already above. // This is converted to SimpleParser and is handled already above.
@@ -646,6 +649,14 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
continue; 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, ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
config_pair.second)); config_pair.second));
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED) LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
@@ -654,11 +665,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
subnet_parser = parser; subnet_parser = parser;
} else if (config_pair.first == "lease-database") { } else if (config_pair.first == "lease-database") {
leases_parser = parser; 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") { } else if (config_pair.first == "hooks-libraries") {
// Executing commit will alter currently-loaded hooks // Executing commit will alter currently-loaded hooks
// libraries. Check if the supplied libraries are valid, // 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. // A Bison parser, made by GNU Bison 3.0.4.
// Locations for Bison parsers in C++ // Locations for Bison parsers in C++

View File

@@ -127,6 +127,8 @@ Parser4Context::contextName()
return ("Logging"); return ("Logging");
case INTERFACES_CONFIG: case INTERFACES_CONFIG:
return ("interfaces-config"); return ("interfaces-config");
case DHCP_SOCKET_TYPE:
return ("dhcp-socket-type");
case LEASE_DATABASE: case LEASE_DATABASE:
return ("lease-database"); return ("lease-database");
case HOSTS_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 // 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 // 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. /// Used while parsing Dhcp4/interfaces structures.
INTERFACES_CONFIG, INTERFACES_CONFIG,
/// Used while parsing Dhcp4/interfaces/dhcp-socket-type structures.
DHCP_SOCKET_TYPE,
/// Used while parsing Dhcp4/lease-database structures. /// Used while parsing Dhcp4/lease-database structures.
LEASE_DATABASE, LEASE_DATABASE,

View File

@@ -1,4 +1,4 @@
// Generated 201612201711 // Generated 201701062338
// A Bison parser, made by GNU Bison 3.0.4. // A Bison parser, made by GNU Bison 3.0.4.
// Positions for Bison parsers in C++ // 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. // A Bison parser, made by GNU Bison 3.0.4.
// Stack handling for Bison parsers in C++ // 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) ) { (config_id.compare("dhcp4o6-port") == 0) ) {
parser = new Uint32Parser(config_id, parser = new Uint32Parser(config_id,
globalContext()->uint32_values_); globalContext()->uint32_values_);
} else if (config_id.compare("interfaces-config") == 0) {
parser = new IfacesConfigParser6();
} else if (config_id.compare("subnet6") == 0) { } else if (config_id.compare("subnet6") == 0) {
parser = new Subnets6ListConfigParser(config_id); parser = new Subnets6ListConfigParser(config_id);
// option-data and option-def are no longer needed here. They're now // option-data and option-def are no longer needed here. They're now
// converted to SimpleParser and are handled in configureDhcp6Server // converted to SimpleParser and are handled in configureDhcp6Server.
} else if (config_id.compare("version") == 0) { // interfaces-config has been converted to SimpleParser.
parser = new StringParser(config_id, // version was removed - it was a leftover from bindctrl.
globalContext()->string_values_);
} else if (config_id.compare("lease-database") == 0) { } else if (config_id.compare("lease-database") == 0) {
parser = new DbAccessParser(config_id, DbAccessParser::LEASE_DB); parser = new DbAccessParser(config_id, DbAccessParser::LEASE_DB);
} else if (config_id.compare("hosts-database") == 0) { } 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! // Please do not change this order!
ParserCollection independent_parsers; ParserCollection independent_parsers;
ParserPtr subnet_parser; ParserPtr subnet_parser;
ParserPtr iface_parser;
ParserPtr leases_parser; ParserPtr leases_parser;
ParserPtr client_classes_parser; ParserPtr client_classes_parser;
@@ -891,6 +887,11 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
} }
BOOST_FOREACH(config_pair, values_map) { 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") { if (config_pair.first == "option-def") {
// This is converted to SimpleParser and is handled already above. // This is converted to SimpleParser and is handled already above.
@@ -931,6 +932,13 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
continue; 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, ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
config_pair.second)); config_pair.second));
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED) LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
@@ -946,11 +954,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
// committed. // committed.
hooks_parser = parser; hooks_parser = parser;
hooks_parser->build(config_pair.second); 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") { } else if (config_pair.first == "client-classes") {
client_classes_parser = parser; client_classes_parser = parser;
} else { } else {

View File

@@ -18,82 +18,56 @@ using namespace isc::data;
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
InterfaceListConfigParser::InterfaceListConfigParser(const uint16_t protocol)
: protocol_(protocol) {
}
void void
InterfaceListConfigParser::build(ConstElementPtr value) { IfacesConfigParser::parseInterfacesList(const CfgIfacePtr& cfg_iface,
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface(); ConstElementPtr ifaces_list) {
BOOST_FOREACH(ConstElementPtr iface, ifaces_list->listValue()) {
BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
std::string iface_name = iface->stringValue(); std::string iface_name = iface->stringValue();
try { try {
cfg_iface->use(protocol_, iface_name); cfg_iface->use(protocol_, iface_name);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
isc_throw(DhcpConfigError, "Failed to select interface: " 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) IfacesConfigParser::IfacesConfigParser(const uint16_t protocol)
: protocol_(protocol) { : protocol_(protocol) {
} }
void void
IfacesConfigParser::build(isc::data::ConstElementPtr ifaces_config) { IfacesConfigParser::parse(const CfgIfacePtr& cfg,
BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) { const isc::data::ConstElementPtr& ifaces_config) {
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);
// Get the pointer to the interface configuration. // Get the pointer to the interface configuration.
CfgIfacePtr cfg = CfgMgr::instance().getStagingCfg()->getCfgIface();
bool socket_type_specified = false; bool socket_type_specified = false;
BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) { BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
try { try {
if (element.first == "dhcp-socket-type") { if (element.first == "interfaces") {
cfg->useSocketType(AF_INET, element.second->stringValue()); parseInterfacesList(cfg, element.second);
socket_type_specified = true; 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) { } catch (const std::exception& ex) {
// Append line number where the error occurred. // Append line number where the error occurred.
isc_throw(DhcpConfigError, ex.what() << " (" 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 // User hasn't specified the socket type. Log that we are using
// the default type. // the default type. Log it only if this is DHCPv4. (DHCPv6 does not use
if (!socket_type_specified) { // raw sockets).
if (!socket_type_specified && (protocol_ == AF_INET) ) {
LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_SOCKET_TYPE_DEFAULT) LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_SOCKET_TYPE_DEFAULT)
.arg(cfg->socketTypeToText()); .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::dhcp
} // end of namespace isc } // 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 // 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 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8,65 +8,22 @@
#define IFACES_CONFIG_PARSER_H #define IFACES_CONFIG_PARSER_H
#include <cc/data.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> #include <dhcpsrv/parsers/dhcp_parsers.h>
namespace isc { namespace isc {
namespace dhcp { 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. /// @brief Parser for the configuration of interfaces.
/// ///
/// This parser parses the "interfaces-config" parameter which holds the /// This parser parses the "interfaces-config" parameter which holds the
/// full configuration of the DHCP server with respect to the use of /// 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 /// This parser is used in both DHCPv4 and DHCPv6. Derived parsers
/// list of interfaces on which the server should listen. It handles /// are not needed.
/// remaining parameters internally. class IfacesConfigParser : public isc::data::SimpleParser {
///
/// This parser is used as a base for the DHCPv4 and DHCPv6 specific
/// parsers and should not be used directly.
class IfacesConfigParser : public DhcpConfigParser {
public: public:
/// @brief Constructor /// @brief Constructor
@@ -74,81 +31,30 @@ public:
/// @param protocol AF_INET for DHCPv4 and AF_INET6 for DHCPv6. /// @param protocol AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
IfacesConfigParser(const uint16_t protocol); 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 /// @param config parsed structures will be stored here
/// the ones that are common for DHCPv4 and DHCPv6. /// @param values pointer to the content of parsed values
/// ///
/// @param ifaces_config A data element holding configuration of /// @throw DhcpConfigError if the interface names and/or addresses
/// interfaces. /// are invalid.
virtual void build(isc::data::ConstElementPtr ifaces_config); void parse(const CfgIfacePtr& config, const isc::data::ConstElementPtr& values);
/// @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;
private: 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. /// @brief AF_INET for DHCPv4 and AF_INET6 for DHCPv6.
int protocol_; 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); ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration. // Parse the configuration.
IfacesConfigParser4 parser; IfacesConfigParser parser(AF_INET);
ASSERT_NO_THROW(parser.build(config_element)); CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
// Open sockets according to the parsed configuration. // Open sockets according to the parsed configuration.
SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg(); SrvConfigPtr cfg = CfgMgr::instance().getStagingCfg();
@@ -77,7 +78,8 @@ TEST_F(IfacesConfigParserTest, interfaces) {
config = "{ \"interfaces\": [ \"eth0\", \"*\" ] }"; config = "{ \"interfaces\": [ \"eth0\", \"*\" ] }";
config_element = Element::fromJSON(config); 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(); cfg = CfgMgr::instance().getStagingCfg();
ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000)); ASSERT_NO_THROW(cfg->getCfgIface()->openSockets(AF_INET, 10000));
@@ -100,8 +102,9 @@ TEST_F(IfacesConfigParserTest, socketTypeRaw) {
ElementPtr config_element = Element::fromJSON(config); ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration. // Parse the configuration.
IfacesConfigParser4 parser; IfacesConfigParser parser(AF_INET);
ASSERT_NO_THROW(parser.build(config_element)); CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
// Compare the resulting configuration with a reference // Compare the resulting configuration with a reference
// configuration using the raw socket. // configuration using the raw socket.
@@ -125,8 +128,9 @@ TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
ElementPtr config_element = Element::fromJSON(config); ElementPtr config_element = Element::fromJSON(config);
// Parse the configuration. // Parse the configuration.
IfacesConfigParser4 parser; IfacesConfigParser parser(AF_INET);
ASSERT_NO_THROW(parser.build(config_element)); CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
ASSERT_NO_THROW(parser.parse(cfg_iface, config_element));
// Compare the resulting configuration with a reference // Compare the resulting configuration with a reference
// configuration using the raw socket. // configuration using the raw socket.
@@ -139,18 +143,19 @@ TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
// Test that the configuration rejects the invalid socket type. // Test that the configuration rejects the invalid socket type.
TEST_F(IfacesConfigParserTest, socketTypeInvalid) { TEST_F(IfacesConfigParserTest, socketTypeInvalid) {
// For DHCPv4 we only accept the raw socket or datagram socket. // 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\": [ ]," std::string config = "{ \"interfaces\": [ ],"
"\"dhcp-socket-type\": \"default\" }"; "\"dhcp-socket-type\": \"default\" }";
ElementPtr config_element = Element::fromJSON(config); 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. // For DHCPv6 we don't accept any socket type.
IfacesConfigParser6 parser6; IfacesConfigParser parser6(AF_INET6);
config = "{ \"interfaces\": [ ]," config = "{ \"interfaces\": [ ],"
" \"dhcp-socket-type\": \"udp\" }"; " \"dhcp-socket-type\": \"udp\" }";
config_element = Element::fromJSON(config); 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 } // end of anonymous namespace