Browse Source

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

# Conflicts:
#	src/bin/dhcp4/json_config_parser.cc
#	src/bin/dhcp6/json_config_parser.cc
Tomek Mrugalski 8 years ago
parent
commit
3d8e48c640

File diff suppressed because it is too large
+ 651 - 626
src/bin/dhcp4/dhcp4_lexer.cc


+ 19 - 1
src/bin/dhcp4/dhcp4_lexer.ll

@@ -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
+ 1132 - 1110
src/bin/dhcp4/dhcp4_parser.cc


+ 142 - 115
src/bin/dhcp4/dhcp4_parser.h

@@ -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
       };
     };
 
@@ -604,6 +607,14 @@ namespace isc { namespace dhcp {
 
     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);
 
     static inline
@@ -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]);
   }
@@ -1590,6 +1605,18 @@ namespace isc { namespace dhcp {
   }
 
   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)
   {
     return symbol_type (token::TOKEN_ECHO_CLIENT_ID, 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
 
 
 

+ 15 - 9
src/bin/dhcp4/dhcp4_parser.yy

@@ -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)));

+ 14 - 8
src/bin/dhcp4/json_config_parser.cc

@@ -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,

+ 1 - 1
src/bin/dhcp4/location.hh

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

+ 2 - 0
src/bin/dhcp4/parser_context.cc

@@ -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:

+ 4 - 1
src/bin/dhcp4/parser_context.h

@@ -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,
 

+ 1 - 1
src/bin/dhcp4/position.hh

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

+ 1 - 1
src/bin/dhcp4/stack.hh

@@ -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++

+ 15 - 12
src/bin/dhcp6/json_config_parser.cc

@@ -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 {

+ 29 - 77
src/lib/dhcpsrv/parsers/ifaces_config_parser.cc

@@ -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

+ 23 - 117
src/lib/dhcpsrv/parsers/ifaces_config_parser.h

@@ -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.
-///
-/// This parser uses the @c InterfaceListConfigParser to parse the
-/// list of interfaces on which the server should listen. It handles
-/// remaining parameters internally.
+/// interfaces, DHCP traffic sockets and alike.
 ///
-/// 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() { }
+    /// @throw DhcpConfigError if the interface names and/or addresses
+    /// are invalid.
+    void parse(const CfgIfacePtr& config, const isc::data::ConstElementPtr& values);
 
-    /// @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.
+private:
+    /// @brief parses interfaces-list structure
     ///
-    /// @param parameter A name of the parameter.
+    /// This method goes through all the interfaces-specified in
+    /// 'interfaces-list' and enabled them in the specified configuration
+    /// structure
     ///
-    /// @return true if the specified parameter is a common parameter
-    /// for DHCPv4 and DHCPv6 server.
-    bool isGenericParameter(const std::string& parameter) const;
-
-private:
+    /// @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);
-
 };
 
 }

+ 16 - 11
src/lib/dhcpsrv/tests/ifaces_config_parser_unittest.cc

@@ -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