Browse Source

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

Francis Dupont 8 years ago
parent
commit
28a9a845a3

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+1207.	[func]		fdupont
+	Client classes parser migrated to SimpleParser. The 'name'
+	parameter in 'client-classes' definitions is now mandatory.
+	(Trac #5098, git xxx)
+
 1206.	[func]		tomek
 	'hooks-libraries' parser migrated to SimpleParser. The code will
 	now refuse a configuration if a hook library fails to load.

File diff suppressed because it is too large
+ 1259 - 1232
src/bin/dhcp4/dhcp4_parser.cc


+ 20 - 20
src/bin/dhcp4/dhcp4_parser.h

@@ -40,7 +40,7 @@
 #ifndef YY_PARSER4_DHCP4_PARSER_H_INCLUDED
 # define YY_PARSER4_DHCP4_PARSER_H_INCLUDED
 // //                    "%code requires" blocks.
-#line 17 "dhcp4_parser.yy" // lalr1.cc:377
+#line 17 "dhcp4_parser.yy" // lalr1.cc:392
 
 #include <string>
 #include <cc/data.h>
@@ -52,7 +52,7 @@ using namespace isc::dhcp;
 using namespace isc::data;
 using namespace std;
 
-#line 56 "dhcp4_parser.h" // lalr1.cc:377
+#line 56 "dhcp4_parser.h" // lalr1.cc:392
 
 # include <cassert>
 # include <cstdlib> // std::abort
@@ -135,9 +135,9 @@ using namespace std;
 # endif /* ! defined YYDEBUG */
 #endif  /* ! defined PARSER4_DEBUG */
 
-#line 14 "dhcp4_parser.yy" // lalr1.cc:377
+#line 14 "dhcp4_parser.yy" // lalr1.cc:392
 namespace isc { namespace dhcp {
-#line 141 "dhcp4_parser.h" // lalr1.cc:377
+#line 141 "dhcp4_parser.h" // lalr1.cc:392
 
 
 
@@ -1312,8 +1312,8 @@ namespace isc { namespace dhcp {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 728,     ///< Last index in yytable_.
-      yynnts_ = 303,  ///< Number of nonterminal symbols.
+      yylast_ = 732,     ///< Last index in yytable_.
+      yynnts_ = 305,  ///< Number of nonterminal symbols.
       yyfinal_ = 24, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
@@ -1408,9 +1408,9 @@ namespace isc { namespace dhcp {
       switch (other.type_get ())
     {
       case 145: // value
-      case 184: // socket_type
-      case 397: // ncr_protocol_value
-      case 406: // replace_client_name_value
+      case 186: // socket_type
+      case 399: // ncr_protocol_value
+      case 408: // replace_client_name_value
         value.copy< ElementPtr > (other.value);
         break;
 
@@ -1448,9 +1448,9 @@ namespace isc { namespace dhcp {
       switch (this->type_get ())
     {
       case 145: // value
-      case 184: // socket_type
-      case 397: // ncr_protocol_value
-      case 406: // replace_client_name_value
+      case 186: // socket_type
+      case 399: // ncr_protocol_value
+      case 408: // replace_client_name_value
         value.copy< ElementPtr > (v);
         break;
 
@@ -1547,9 +1547,9 @@ namespace isc { namespace dhcp {
     switch (yytype)
     {
       case 145: // value
-      case 184: // socket_type
-      case 397: // ncr_protocol_value
-      case 406: // replace_client_name_value
+      case 186: // socket_type
+      case 399: // ncr_protocol_value
+      case 408: // replace_client_name_value
         value.template destroy< ElementPtr > ();
         break;
 
@@ -1593,9 +1593,9 @@ namespace isc { namespace dhcp {
       switch (this->type_get ())
     {
       case 145: // value
-      case 184: // socket_type
-      case 397: // ncr_protocol_value
-      case 406: // replace_client_name_value
+      case 186: // socket_type
+      case 399: // ncr_protocol_value
+      case 408: // replace_client_name_value
         value.move< ElementPtr > (s.value);
         break;
 
@@ -2469,9 +2469,9 @@ namespace isc { namespace dhcp {
   }
 
 
-#line 14 "dhcp4_parser.yy" // lalr1.cc:377
+#line 14 "dhcp4_parser.yy" // lalr1.cc:392
 } } // isc::dhcp
-#line 2475 "dhcp4_parser.h" // lalr1.cc:377
+#line 2475 "dhcp4_parser.h" // lalr1.cc:392
 
 
 

+ 24 - 10
src/bin/dhcp4/dhcp4_parser.yy

@@ -274,14 +274,6 @@ list_generic: LSQUARE_BRACKET {
     // list parsing complete. Put any sanity checking here
 };
 
-// This one is used in syntax parser.
-list2: LSQUARE_BRACKET {
-    // List parsing about to start
-} list_content RSQUARE_BRACKET {
-    // list parsing complete. Put any sanity checking here
-    //ctx.stack_.pop_back();
-};
-
 list_content: %empty // Empty list
             | not_empty_list
             ;
@@ -296,6 +288,28 @@ not_empty_list: value {
                   }
               ;
 
+// This one is used in syntax parser and is restricted to strings.
+list_strings: LSQUARE_BRACKET {
+    // List parsing about to start
+} list_strings_content RSQUARE_BRACKET {
+    // list parsing complete. Put any sanity checking here
+    //ctx.stack_.pop_back();
+};
+
+list_strings_content: %empty // Empty list
+                    | not_empty_list_strings
+                    ;
+
+not_empty_list_strings: STRING {
+                          ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      | not_empty_list_strings COMMA STRING {
+                          ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      ;
+
 // ---- generic JSON parser ends here ----------------------------------
 
 // ---- syntax checking parser starts here -----------------------------
@@ -452,7 +466,7 @@ interfaces_list: INTERFACES {
     ctx.stack_.back()->set("interfaces", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.leave();
 };
@@ -1260,7 +1274,7 @@ reservation_client_classes: CLIENT_CLASSES {
     ctx.stack_.back()->set("client-classes", c);
     ctx.stack_.push_back(c);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.leave();
 };

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

@@ -437,8 +437,7 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
         parser = new BooleanParser(config_id, globalContext()->boolean_values_);
     // control-socket has been converted to SimpleParser already.
     // expired-leases-processing has been converted to SimpleParser already.
-    } else if (config_id.compare("client-classes") == 0) {
-        parser = new ClientClassDefListParser(config_id, globalContext());
+    // client-classes has been converted to SimpleParser already.
     // host-reservation-identifiers have been converted to SimpleParser already.
     } else {
         isc_throw(DhcpConfigError,
@@ -568,7 +567,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
     ParserCollection independent_parsers;
     ParserPtr subnet_parser;
     ParserPtr leases_parser;
-    ParserPtr client_classes_parser;
 
     // Some of the parsers alter the state of the system in a way that can't
     // easily be undone. (Or alter it in a way such that undoing the change has
@@ -677,6 +675,14 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
                 continue;
             }
 
+            if (config_pair.first == "client-classes") {
+                ClientClassDefListParser parser;
+                ClientClassDictionaryPtr dictionary =
+                    parser.parse(config_pair.second, AF_INET);
+                CfgMgr::instance().getStagingCfg()->setClientClassDictionary(dictionary);
+                continue;
+            }
+
             ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
                                                            config_pair.second));
             LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
@@ -685,8 +691,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
                 subnet_parser = parser;
             } else if (config_pair.first == "lease-database") {
                 leases_parser = parser;
-            } else if (config_pair.first == "client-classes") {
-                client_classes_parser = parser;
             } else {
                 // Those parsers should be started before other
                 // parsers so we can call build straight away.
@@ -699,15 +703,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
             }
         }
 
-        // The class definitions parser is the next one to be run.
-        std::map<std::string, ConstElementPtr>::const_iterator cc_config =
-            values_map.find("client-classes");
-        if (cc_config != values_map.end()) {
-            config_pair.first = "client-classes";
-            client_classes_parser->build(cc_config->second);
-            client_classes_parser->commit();
-        }
-
         // The subnet parser is the next one to be run.
         std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
             values_map.find("subnet4");

File diff suppressed because it is too large
+ 1299 - 1273
src/bin/dhcp6/dhcp6_parser.cc


+ 20 - 20
src/bin/dhcp6/dhcp6_parser.h

@@ -40,7 +40,7 @@
 #ifndef YY_PARSER6_DHCP6_PARSER_H_INCLUDED
 # define YY_PARSER6_DHCP6_PARSER_H_INCLUDED
 // //                    "%code requires" blocks.
-#line 17 "dhcp6_parser.yy" // lalr1.cc:377
+#line 17 "dhcp6_parser.yy" // lalr1.cc:392
 
 #include <string>
 #include <cc/data.h>
@@ -52,7 +52,7 @@ using namespace isc::dhcp;
 using namespace isc::data;
 using namespace std;
 
-#line 56 "dhcp6_parser.h" // lalr1.cc:377
+#line 56 "dhcp6_parser.h" // lalr1.cc:392
 
 # include <cassert>
 # include <cstdlib> // std::abort
@@ -135,9 +135,9 @@ using namespace std;
 # endif /* ! defined YYDEBUG */
 #endif  /* ! defined PARSER6_DEBUG */
 
-#line 14 "dhcp6_parser.yy" // lalr1.cc:377
+#line 14 "dhcp6_parser.yy" // lalr1.cc:392
 namespace isc { namespace dhcp {
-#line 141 "dhcp6_parser.h" // lalr1.cc:377
+#line 141 "dhcp6_parser.h" // lalr1.cc:392
 
 
 
@@ -1327,8 +1327,8 @@ namespace isc { namespace dhcp {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 742,     ///< Last index in yytable_.
-      yynnts_ = 310,  ///< Number of nonterminal symbols.
+      yylast_ = 752,     ///< Last index in yytable_.
+      yynnts_ = 312,  ///< Number of nonterminal symbols.
       yyfinal_ = 26, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
@@ -1423,9 +1423,9 @@ namespace isc { namespace dhcp {
       switch (other.type_get ())
     {
       case 149: // value
-      case 374: // duid_type
-      case 407: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 376: // duid_type
+      case 409: // ncr_protocol_value
+      case 418: // replace_client_name_value
         value.copy< ElementPtr > (other.value);
         break;
 
@@ -1463,9 +1463,9 @@ namespace isc { namespace dhcp {
       switch (this->type_get ())
     {
       case 149: // value
-      case 374: // duid_type
-      case 407: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 376: // duid_type
+      case 409: // ncr_protocol_value
+      case 418: // replace_client_name_value
         value.copy< ElementPtr > (v);
         break;
 
@@ -1562,9 +1562,9 @@ namespace isc { namespace dhcp {
     switch (yytype)
     {
       case 149: // value
-      case 374: // duid_type
-      case 407: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 376: // duid_type
+      case 409: // ncr_protocol_value
+      case 418: // replace_client_name_value
         value.template destroy< ElementPtr > ();
         break;
 
@@ -1608,9 +1608,9 @@ namespace isc { namespace dhcp {
       switch (this->type_get ())
     {
       case 149: // value
-      case 374: // duid_type
-      case 407: // ncr_protocol_value
-      case 416: // replace_client_name_value
+      case 376: // duid_type
+      case 409: // ncr_protocol_value
+      case 418: // replace_client_name_value
         value.move< ElementPtr > (s.value);
         break;
 
@@ -2502,9 +2502,9 @@ namespace isc { namespace dhcp {
   }
 
 
-#line 14 "dhcp6_parser.yy" // lalr1.cc:377
+#line 14 "dhcp6_parser.yy" // lalr1.cc:392
 } } // isc::dhcp
-#line 2508 "dhcp6_parser.h" // lalr1.cc:377
+#line 2508 "dhcp6_parser.h" // lalr1.cc:392
 
 
 

+ 29 - 13
src/bin/dhcp6/dhcp6_parser.yy

@@ -277,14 +277,6 @@ list_generic: LSQUARE_BRACKET {
     // list parsing complete. Put any sanity checking here
 };
 
-// This one is used in syntax parser.
-list2: LSQUARE_BRACKET {
-    // List parsing about to start
-} list_content RSQUARE_BRACKET {
-    // list parsing complete. Put any sanity checking here
-    //ctx.stack_.pop_back();
-};
-
 list_content: %empty // Empty list
             | not_empty_list
             ;
@@ -299,6 +291,28 @@ not_empty_list: value {
                   }
               ;
 
+// This one is used in syntax parser and is restricted to strings.
+list_strings: LSQUARE_BRACKET {
+    // List parsing about to start
+} list_strings_content RSQUARE_BRACKET {
+    // list parsing complete. Put any sanity checking here
+    //ctx.stack_.pop_back();
+};
+
+list_strings_content: %empty // Empty list
+                    | not_empty_list_strings
+                    ;
+
+not_empty_list_strings: STRING {
+                          ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      | not_empty_list_strings COMMA STRING {
+                          ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      ;
+
 // ---- generic JSON parser ends here ----------------------------------
 
 // ---- syntax checking parser starts here -----------------------------
@@ -441,7 +455,7 @@ interface_config_map: INTERFACES {
     ctx.stack_.back()->set("interfaces", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.leave();
 };
@@ -587,12 +601,14 @@ hw_address_id : HW_ADDRESS {
     ctx.stack_.back()->add(hwaddr);
 };
 
+// list_content below accepts any value when options are by name (string)
+// or by code (number)
 relay_supplied_options: RELAY_SUPPLIED_OPTIONS {
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("relay-supplied-options", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON LSQUARE_BRACKET list_content RSQUARE_BRACKET {
     ctx.stack_.pop_back();
     ctx.leave();
 };
@@ -1244,7 +1260,7 @@ ip_addresses: IP_ADDRESSES {
     ctx.stack_.back()->set("ip-addresses", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.leave();
 };
@@ -1254,7 +1270,7 @@ prefixes: PREFIXES  {
     ctx.stack_.back()->set("prefixes", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.leave();
 };
@@ -1288,7 +1304,7 @@ reservation_client_classes: CLIENT_CLASSES {
     ctx.stack_.back()->set("client-classes", c);
     ctx.stack_.push_back(c);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.leave();
 };

+ 9 - 14
src/bin/dhcp6/json_config_parser.cc

@@ -716,8 +716,7 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
         parser = new RSOOListConfigParser(config_id);
     // control-socket has been converted to SimpleParser.
     // expired-leases-processing has been converted to SimpleParser.
-    } else if (config_id.compare("client-classes") == 0) {
-        parser = new ClientClassDefListParser(config_id, globalContext());
+    // client-classes has been converted to SimpleParser.
     // host-reservation-identifiers have been converted to SimpleParser already.
     // server-id has been migrated to SimpleParser
     } else {
@@ -837,7 +836,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
     ParserCollection independent_parsers;
     ParserPtr subnet_parser;
     ParserPtr leases_parser;
-    ParserPtr client_classes_parser;
 
     // Some of the parsers alter state of the system that can't easily
     // be undone. (Or alter it in a way such that undoing the change
@@ -959,6 +957,14 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
                 continue;
             }
 
+            if (config_pair.first =="client-classes") {
+                ClientClassDefListParser parser;
+                ClientClassDictionaryPtr dictionary =
+                    parser.parse(config_pair.second, AF_INET6);
+                CfgMgr::instance().getStagingCfg()->setClientClassDictionary(dictionary);
+                continue;
+            }
+
             ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
                                                            config_pair.second));
             LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
@@ -967,8 +973,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
                 subnet_parser = parser;
             } else if (config_pair.first == "lease-database") {
                 leases_parser = parser;
-            } else if (config_pair.first == "client-classes") {
-                client_classes_parser = parser;
             } else {
                 // Those parsers should be started before other
                 // parsers so we can call build straight away.
@@ -981,15 +985,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
             }
         }
 
-        // The class definitions parser is the next one to be run.
-        std::map<std::string, ConstElementPtr>::const_iterator cc_config =
-            values_map.find("client-classes");
-        if (cc_config != values_map.end()) {
-            config_pair.first = "client-classes";
-            client_classes_parser->build(cc_config->second);
-            client_classes_parser->commit();
-        }
-
         // The subnet parser is the next one to be run.
         std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
             values_map.find("subnet6");

+ 68 - 104
src/lib/dhcpsrv/parsers/client_class_def_parser.cc

@@ -1,12 +1,13 @@
-// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-#include <cc/data.h>
+#include <config.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/client_class_def.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
 #include <eval/eval_context.h>
 #include <asiolink/io_address.h>
@@ -18,7 +19,7 @@ using namespace isc::data;
 using namespace isc::asiolink;
 using namespace std;
 
-/// @file client_class_def.cc
+/// @file client_class_def_parser.cc
 ///
 /// @brief Method implementations for client class definition parsing
 
@@ -27,14 +28,10 @@ namespace dhcp {
 
 // ********************** ExpressionParser ****************************
 
-ExpressionParser::ExpressionParser(const std::string&,
-    ExpressionPtr& expression, ParserContextPtr global_context)
-    : local_expression_(ExpressionPtr()), expression_(expression),
-      global_context_(global_context) {
-}
-
 void
-ExpressionParser::build(ConstElementPtr expression_cfg) {
+ExpressionParser::parse(ExpressionPtr& expression,
+                        ConstElementPtr expression_cfg,
+                        uint16_t family) {
     if (expression_cfg->getType() != Element::string) {
         isc_throw(DhcpConfigError, "expression ["
             << expression_cfg->str() << "] must be a string, at ("
@@ -46,10 +43,10 @@ ExpressionParser::build(ConstElementPtr expression_cfg) {
     std::string value;
     expression_cfg->getValue(value);
     try {
-        EvalContext eval_ctx(global_context_->universe_);
+        EvalContext eval_ctx(family == AF_INET ? Option::V4 : Option::V6);
         eval_ctx.parseString(value);
-        local_expression_.reset(new Expression());
-        *local_expression_ = eval_ctx.expression;
+        expression.reset(new Expression());
+        *expression = eval_ctx.expression;
     } catch (const std::exception& ex) {
         // Append position if there is a failure.
         isc_throw(DhcpConfigError,
@@ -59,74 +56,60 @@ ExpressionParser::build(ConstElementPtr expression_cfg) {
     }
 }
 
-void
-ExpressionParser::commit() {
-    expression_ = local_expression_;
-}
-
 // ********************** ClientClassDefParser ****************************
 
-ClientClassDefParser::ClientClassDefParser(const std::string&,
-    ClientClassDictionaryPtr& class_dictionary, ParserContextPtr global_context)
-    : string_values_(new StringStorage()),
-      match_expr_(ExpressionPtr()),
-      options_(new CfgOption()),
-      class_dictionary_(class_dictionary),
-      global_context_(global_context) {
-}
-
 void
-ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
-
-    // Parse the elements that make up the option definition.
-    BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
-        std::string entry(param.first);
-        ParserPtr parser;
-        if (entry == "name") {
-            StringParserPtr str_parser(new StringParser(entry, string_values_));
-            parser = str_parser;
-        } else if (entry == "test") {
-            ExpressionParserPtr exp_parser(new ExpressionParser(entry,
-                                                                match_expr_,
-                                                                global_context_));
-            parser = exp_parser;
-        } else if (entry == "option-data") {
-
-            uint16_t family = (global_context_->universe_ == Option::V4 ?
-                                                             AF_INET : AF_INET6);
-
-            OptionDataListParser opts_parser(family);
-            opts_parser.parse(options_, param.second);
-
-            // OptionDataListParser is converted to SimpleParser already,
-            // no need to go through build/commit phases.
-            continue;
-        } else if (entry == "next-server") {
-            StringParserPtr str_parser(new StringParser(entry, string_values_));
-            parser = str_parser;
-        } else if (entry == "server-hostname") {
-            StringParserPtr str_parser(new StringParser(entry, string_values_));
-            parser = str_parser;
-
-        } else if (entry == "boot-file-name") {
-            StringParserPtr str_parser(new StringParser(entry, string_values_));
-            parser = str_parser;
-        } else {
-            isc_throw(DhcpConfigError, "invalid parameter '" << entry
-                      << "' (" << param.second->getPosition() << ")");
-        }
+ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
+                            ConstElementPtr class_def_cfg,
+                            uint16_t family) {
 
-        parser->build(param.second);
-        parser->commit();
-    }
-
-    std::string name;
     try {
-        name = string_values_->getParam("name");
+        std::string name;
+        std::string next_server_txt = "0.0.0.0";
+        std::string sname;
+        std::string filename;
+        ExpressionPtr match_expr;
+        CfgOptionPtr options(new CfgOption());
+
+        // Parse the elements that make up the client class definition.
+        BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
+            std::string entry(param.first);
+            ConstElementPtr value(param.second);
+
+            if (entry == "name") {
+                name = value->stringValue();
+
+            } else if (entry == "test") {
+                ExpressionParser parser;
+                parser.parse(match_expr, value, family);
+                
+            } else if (entry == "option-data") {
+                OptionDataListParser opts_parser(family);
+                opts_parser.parse(options, value);
+
+            } else if (entry == "next-server") {
+                next_server_txt = value->stringValue();
+
+            } else if (entry == "server-hostname") {
+                sname = value->stringValue();
+
+            } else if (entry == "boot-file-name") {
+                filename = value->stringValue();
+
+            } else {
+                isc_throw(DhcpConfigError, "invalid parameter '" << entry
+                          << "' (" << value->getPosition() << ")");
+            }
+        }
+
+        // name is now mandatory
+        if (name.empty()) {
+            isc_throw(DhcpConfigError,
+                      "not empty parameter 'name' is required");
+        }
 
         // Let's parse the next-server field
         IOAddress next_server("0.0.0.0");
-        string next_server_txt = string_values_->getOptionalParam("next-server", "0.0.0.0");
         try {
             next_server = IOAddress(next_server_txt);
         } catch (const IOError& ex) {
@@ -144,24 +127,23 @@ ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
                       << next_server_txt << "', must not be a broadcast");
         }
 
-        // Let's try to parse sname
-        string sname = string_values_->getOptionalParam("server-hostname", "");
+        // Let's try to parse server-hostname
         if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
             isc_throw(DhcpConfigError, "server-hostname must be at most "
                       << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
                       << sname.length());
         }
 
-        string filename = string_values_->getOptionalParam("boot-file-name", "");
+        // Let's try to parse boot-file-name
         if (filename.length() > Pkt4::MAX_FILE_LEN) {
             isc_throw(DhcpConfigError, "boot-file-name must be at most "
                       << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
                       << filename.length());
         }
 
-        // an OptionCollectionPtr
-        class_dictionary_->addClass(name, match_expr_, options_, next_server,
-                                    sname, filename);
+        // Add the client class definition
+        class_dictionary->addClass(name, match_expr, options, next_server,
+                                   sname, filename);
     } catch (const std::exception& ex) {
         isc_throw(DhcpConfigError, ex.what()
                   << " (" << class_def_cfg->getPosition() << ")");
@@ -170,34 +152,16 @@ ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
 
 // ****************** ClientClassDefListParser ************************
 
-ClientClassDefListParser::ClientClassDefListParser(const std::string&,
-                                                   ParserContextPtr
-                                                   global_context)
-    : local_dictionary_(new ClientClassDictionary()),
-      global_context_(global_context) {
-}
-
-void
-ClientClassDefListParser::build(ConstElementPtr client_class_def_list) {
-    if (!client_class_def_list) {
-        isc_throw(DhcpConfigError, "parser error: a pointer to a list of"
-                  << " client class definitions is NULL ("
-                  << client_class_def_list->getPosition() << ")");
-    }
-
+ClientClassDictionaryPtr
+ClientClassDefListParser::parse(ConstElementPtr client_class_def_list,
+                                uint16_t family) {
+    ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
     BOOST_FOREACH(ConstElementPtr client_class_def,
                   client_class_def_list->listValue()) {
-        boost::shared_ptr<ClientClassDefParser>
-            parser(new ClientClassDefParser("client-class-def",
-                                            local_dictionary_,
-                                            global_context_));
-        parser->build(client_class_def);
+        ClientClassDefParser parser;
+        parser.parse(dictionary, client_class_def, family);
     }
-}
-
-void
-ClientClassDefListParser::commit() {
-    CfgMgr::instance().getStagingCfg()->setClientClassDictionary(local_dictionary_);
+    return (dictionary);
 }
 
 } // end of namespace isc::dhcp

+ 26 - 94
src/lib/dhcpsrv/parsers/client_class_def_parser.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015, 2017 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7,10 +7,11 @@
 #ifndef CLIENT_CLASS_DEF_PARSER_H
 #define CLIENT_CLASS_DEF_PARSER_H
 
+#include <cc/data.h>
+#include <cc/simple_parser.h>
 #include <dhcpsrv/client_class_def.h>
-#include <dhcpsrv/parsers/dhcp_parsers.h>
 
-/// @file client_class_def.h
+/// @file client_class_def_parser.h
 ///
 /// @brief Parsers for client class definitions
 ///
@@ -22,11 +23,10 @@
 /// There parsers defined are:
 ///
 /// ClientClassDefListParser  - creates a ClientClassDictionary from a list
-/// of element maps, where each map contains the entries that specifiy a
+/// of element maps, where each map contains the entries that specify a
 /// single class.  The names of the classes in the are expected to be
 /// unique.  Attempting to define a duplicate class will result in an
-/// DhcpConfigError throw.  Invoking @c commit() method causes the dictionary
-/// to be stored by the CfgMgr.
+/// DhcpConfigError throw.  At the end the dictionary is stored by the CfgMgr.
 ///
 /// ClientClassDefParser - creates a ClientClassDefinition from an element
 /// map. The elements are as follows:
@@ -37,7 +37,7 @@
 /// membership in the class. This is passed into the eval parser.
 ///
 /// -# "option-data" - a list which defines the options that should be
-/// assigned to memebers of the class.  This element is optional and parsed
+/// assigned to remembers of the class.  This element is optional and parsed
 /// using the @ref isc::dhcp::OptionDataListParser.
 ///
 /// ExpressionParser  - creates an eval::Expression from a string element,
@@ -51,87 +51,37 @@ namespace dhcp {
 /// This parser creates an instance of an Expression from a string.  The
 /// string is passed to the Eval Parser and the resultant Expression is
 /// stored into the ExpressionPtr reference passed into the constructor.
-class ExpressionParser : public DhcpConfigParser {
+class ExpressionParser : public isc::data::SimpleParser {
 public:
-    /// @brief Constructor.
-    ///
-    /// @param dummy first argument is ignored, all Parser constructors
-    /// accept string as first argument.
-    /// @param expression variable in which to store the new expression
-    /// @param global_context is a pointer to the global context which
-    /// stores global scope parameters, options, option defintions.
-    ExpressionParser(const std::string& dummy, ExpressionPtr& expression,
-                     ParserContextPtr global_context);
 
     /// @brief Parses an expression configuration element into an Expression
     ///
+    /// @param expression variable in which to store the new expression
     /// @param expression_cfg the configuration entry to be parsed.
+    /// @param family the address family of the expression.
     ///
     /// @throw DhcpConfigError if parsing was unsuccessful.
-    void build(isc::data::ConstElementPtr expression_cfg);
-
-    /// @brief Stores the parsed expression to the supplied storage.
-    void commit();
-
-private:
-    /// @brief Local storage for the parsed expression
-    ExpressionPtr local_expression_;
-
-    /// @brief Storage into which the parsed expression should be committed
-    ExpressionPtr& expression_;
-
-    /// @brief Parsing context which contains global values, options and option
-    /// definitions.
-    ParserContextPtr global_context_;
+    void parse(ExpressionPtr& expression,
+               isc::data::ConstElementPtr expression_cfg, uint16_t family);
 };
 
-typedef boost::shared_ptr<ExpressionParser> ExpressionParserPtr;
-
 /// @brief Parser for a single client class definition.
 ///
 /// This parser creates an instance of a client class definition.
-class ClientClassDefParser : public DhcpConfigParser {
+class ClientClassDefParser : public isc::data::SimpleParser {
 public:
-    /// @brief Constructor.
-    ///
-    /// @param dummy first argument is ignored, all Parser constructors
-    /// accept string as first argument.
-    /// @param class_dictionary dictionary into which the class should be added
-    /// @param global_context is a pointer to the global context which
-    /// stores global scope parameters, options, option defintions.
-    ClientClassDefParser(const std::string& dummy,
-                         ClientClassDictionaryPtr& class_dictionary,
-                         ParserContextPtr global_context);
 
     /// @brief Parses an entry that describes single client class definition.
     ///
-    /// Attempts to add the new class direclty into the given dictionary.
+    /// Attempts to add the new class directly into the given dictionary.
     /// This done here to detect duplicate classes prior to commit().
+    /// @param class_dictionary dictionary into which the class should be added
     /// @param client_class_def a configuration entry to be parsed.
+    /// @param family the address family of the client class.
     ///
     /// @throw DhcpConfigError if parsing was unsuccessful.
-    void build(isc::data::ConstElementPtr client_class_def);
-
-    /// @brief Does nothing.
-    void commit() {};
-
-private:
-
-    /// @brief Storage for class string values.
-    StringStoragePtr string_values_;
-
-    /// @brief Storage for the class match expression
-    ExpressionPtr match_expr_;
-
-    /// @brief Storage for the class options
-    CfgOptionPtr options_;
-
-    /// @brief Dictionary to which the new class should be added
-    ClientClassDictionaryPtr class_dictionary_;
-
-    /// @brief Parsing context which contains global values, options and option
-    /// definitions.
-    ParserContextPtr global_context_;
+    void parse(ClientClassDictionaryPtr& class_dictionary,
+               isc::data::ConstElementPtr client_class_def, uint16_t family);
 };
 
 /// @brief Defines a pointer to a ClientClassDefParser
@@ -141,44 +91,26 @@ typedef boost::shared_ptr<ClientClassDefParser> ClientClassDefParserPtr;
 ///
 /// This parser iterates over all configuration entries that define
 /// client classes and creates ClientClassDef instances for each.
-/// If the parsing done in build() is successful, the collection of
+/// When the parsing successfully completes, the collection of
 /// created definitions is given to the CfgMgr.
-class ClientClassDefListParser : public DhcpConfigParser {
+class ClientClassDefListParser : public isc::data::SimpleParser {
 public:
-    /// @brief Constructor.
-    ///
-    /// @param dummy first argument is ignored, all Parser constructors
-    /// accept string as first argument.
-    /// @param global_context is a pointer to the global context which
-    /// stores global scope parameters, options, option defintions.
-    ClientClassDefListParser(const std::string& dummy,
-                        ParserContextPtr global_context);
 
     /// @brief Parse configuration entries.
     ///
     /// This function parses configuration entries, creates instances
-    /// of client class definitions and tries to adds them to the a
-    /// local dictionary.
+    /// of client class definitions and tries to adds them to the
+    /// local dictionary. At the end the dictionary is returned.
     ///
     /// @param class_def_list pointer to an element that holds entries
     /// for client class definitions.
+    /// @param family the address family of the client class definitions.
+    /// @return a pointer to the filled dictionary
     /// @throw DhcpConfigError if configuration parsing fails.
-    void build(isc::data::ConstElementPtr class_def_list);
-
-    /// @brief Commits class definitions to CfgMgr's global storage.
-    void commit();
-
-    /// @brief Local class dictionary to store classes as they are being parsed
-    ClientClassDictionaryPtr local_dictionary_;
-
-    /// Parsing context which contains global values, options and option
-    /// definitions.
-    ParserContextPtr global_context_;
+    ClientClassDictionaryPtr
+    parse(isc::data::ConstElementPtr class_def_list, uint16_t family);
 };
 
-/// @brief Defines a pointer to a ClientClassDefListParser
-typedef boost::shared_ptr<ClientClassDefListParser> ClientClassDefListParserPtr;
-
 } // end of namespace isc::dhcp
 } // end of namespace isc
 

+ 1 - 1
src/lib/dhcpsrv/srv_config.h

@@ -365,7 +365,7 @@ public:
         class_dictionary_ = dictionary;
     }
 
-    /// @brief Copies the currnet configuration to a new configuration.
+    /// @brief Copies the current configuration to a new configuration.
     ///
     /// This method copies the parameters stored in the configuration to
     /// an object passed as parameter. The configuration sequence is not

+ 81 - 84
src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc

@@ -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
@@ -12,6 +12,7 @@
 #include <dhcp/option_string.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <asiolink/io_address.h>
 #include <eval/evaluate.h>
 #include <gtest/gtest.h>
@@ -39,35 +40,30 @@ protected:
     /// produces an Expression which can be evaluated against a v4 or v6
     /// packet.
     ///
-    /// @param universe V4 or V6.
+    /// @param family AF_INET or AF_INET6
     /// @param expression Textual representation of the expression to be
     /// evaluated.
     /// @param option_string String data to be placed in the hostname
     /// option, being placed in the packet used for evaluation.
     /// @tparam Type of the packet: @c Pkt4 or @c Pkt6.
     template<typename PktType>
-    void testValidExpression(const Option::Universe& universe,
+    void testValidExpression(uint16_t family,
                              const std::string& expression,
                              const std::string& option_string) {
-        ParserContextPtr context(new ParserContext(universe));
-        ExpressionParserPtr parser;
         ExpressionPtr parsed_expr;
+        ExpressionParser parser;
 
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(expression);
 
-        // Create the parser.
-        ASSERT_NO_THROW(parser.reset(new ExpressionParser("", parsed_expr,
-                                                      context)));
-        // Expression should parse and commit.
-        ASSERT_NO_THROW(parser->build(config_element));
-        ASSERT_NO_THROW(parser->commit());
+        // Expression should parse.
+        ASSERT_NO_THROW(parser.parse(parsed_expr, config_element, family));
 
         // Parsed expression should exist.
         ASSERT_TRUE(parsed_expr);
 
         // Build a packet that will fail evaluation.
-        boost::shared_ptr<PktType> pkt(new PktType(universe == Option::V4 ?
+        boost::shared_ptr<PktType> pkt(new PktType(family == AF_INET ?
                                                    DHCPDISCOVER : DHCPV6_SOLICIT,
                                                    123));
         EXPECT_FALSE(evaluate(*parsed_expr, *pkt));
@@ -75,7 +71,8 @@ protected:
         // Now add the option so it will pass. Use a standard option carrying a
         // single string value, i.e. hostname for DHCPv4 and bootfile url for
         // DHCPv6.
-        OptionPtr opt(new OptionString(universe, universe == Option::V4 ?
+        Option::Universe universe(family == AF_INET ? Option::V4 : Option::V6);
+        OptionPtr opt(new OptionString(universe, family == AF_INET ?
                                        DHO_HOST_NAME : D6O_BOOTFILE_URL,
                                        option_string));
         pkt->addOption(opt);
@@ -93,25 +90,23 @@ protected:
     ///
     /// @param config - JSON string containing the client class configuration
     /// to parse.
-    /// @param universe - the universe in which the parsing context should
+    /// @param family - the address family in which the parsing should
     /// occur.
     /// @return Returns a pointer to class instance created, or NULL if
     /// for some unforeseen reason it wasn't created in the local dictionary
     /// @throw indirectly, exceptions convertring the JSON text to elements,
     /// or by the parsing itself are not caught
     ClientClassDefPtr parseClientClassDef(const std::string& config,
-                                          Option::Universe universe) {
-        // Create local dicitonary to which the parser add the class.
+                                          uint16_t family) {
+        // Create local dictionary to which the parser add the class.
         ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
-        // Create the "global" context for the parser.
-        ParserContextPtr context(new ParserContext(universe));
 
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(config);
 
         // Parse the configuration. This may emit exceptions.
-        ClientClassDefParser parser("", dictionary, context);
-        parser.build(config_element);
+        ClientClassDefParser parser;
+        parser.parse(dictionary, config_element, family);
 
         // If we didn't throw, then return the first and only class
         ClientClassDefMapPtr classes = dictionary->getClasses();
@@ -136,42 +131,34 @@ protected:
     /// ClientClassDictionary.
     ///
     /// @param config - JSON string containing the list of definitions to parse.
-    /// @param universe - the universe in which the parsing context should
+    /// @param family - the address family in which the parsing should
     /// occur.
     /// @return Returns a pointer to class dictionary created
     /// @throw indirectly, execptions convertring the JSON text to elements,
     /// or by the parsing itself are not caught
     ClientClassDictionaryPtr parseClientClassDefList(const std::string& config,
-                                                     Option::Universe universe)
+                                                     uint16_t family)
     {
-        // Create the "global" context for the parser.
-        ParserContextPtr context(new ParserContext(universe));
-
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(config);
 
         // Parse the configuration. This may emit exceptions.
-        ClientClassDefListParser parser("", context);
-        parser.build(config_element);
-
-        // Commit should push it to CfgMgr staging
-        parser.commit();
-
-        // Return the parser's local dicationary
-        return (parser.local_dictionary_);
+        ClientClassDefListParser parser;
+        return (parser.parse(config_element, family));
     }
 };
 
 // Verifies that given a valid expression, the ExpressionParser
 // produces an Expression which can be evaluated against a v4 packet.
 TEST_F(ExpressionParserTest, validExpression4) {
-    testValidExpression<Pkt4>(Option::V4, "\"option[12].text == 'hundred4'\"",
+    testValidExpression<Pkt4>(AF_INET,
+                              "\"option[12].text == 'hundred4'\"",
                               "hundred4");
 }
 
 // Verifies that the option name can be used in the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionName4) {
-    testValidExpression<Pkt4>(Option::V4,
+    testValidExpression<Pkt4>(AF_INET,
                               "\"option[host-name].text == 'hundred4'\"",
                               "hundred4");
 }
@@ -180,14 +167,15 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName4) {
 // ExpressionParser produces an Expression which can be evaluated against
 // a v4 packet.
 TEST_F(ExpressionParserTest, validExpressionWithHex4) {
-    testValidExpression<Pkt4>(Option::V4, "\"option[12].hex == 0x68756E6472656434\"",
+    testValidExpression<Pkt4>(AF_INET,
+                              "\"option[12].hex == 0x68756E6472656434\"",
                               "hundred4");
 }
 
 // Verifies that the option name can be used together with .hex operator in
 // the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) {
-    testValidExpression<Pkt6>(Option::V4,
+    testValidExpression<Pkt6>(AF_INET,
                               "\"option[host-name].text == 0x68756E6472656434\"",
                               "hundred4");
 }
@@ -195,13 +183,14 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) {
 // Verifies that given a valid expression, the ExpressionParser
 // produces an Expression which can be evaluated against a v6 packet.
 TEST_F(ExpressionParserTest, validExpression6) {
-    testValidExpression<Pkt6>(Option::V6, "\"option[59].text == 'hundred6'\"",
+    testValidExpression<Pkt6>(AF_INET6,
+                              "\"option[59].text == 'hundred6'\"",
                               "hundred6");
 }
 
 // Verifies that the option name can be used in the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionName6) {
-    testValidExpression<Pkt6>(Option::V6,
+    testValidExpression<Pkt6>(AF_INET6,
                               "\"option[bootfile-url].text == 'hundred6'\"",
                               "hundred6");
 }
@@ -210,33 +199,32 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName6) {
 // ExpressionParser produces an Expression which can be evaluated against
 // a v6 packet.
 TEST_F(ExpressionParserTest, validExpressionWithHex6) {
-    testValidExpression<Pkt6>(Option::V6, "\"option[59].hex == 0x68756E6472656436\"",
+    testValidExpression<Pkt6>(AF_INET6,
+                              "\"option[59].hex == 0x68756E6472656436\"",
                               "hundred6");
 }
 
 // Verifies that the option name can be used together with .hex operator in
 // the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex6) {
-    testValidExpression<Pkt6>(Option::V6,
+    testValidExpression<Pkt6>(AF_INET6,
                               "\"option[bootfile-url].text == 0x68756E6472656436\"",
                               "hundred6");
 }
 
 // Verifies that an the ExpressionParser only accepts StringElements.
 TEST_F(ExpressionParserTest, invalidExpressionElement) {
-    ParserContextPtr context(new ParserContext(Option::V4));
-    ExpressionParserPtr parser;
-    ExpressionPtr parsed_expr;
-
     // This will create an integer element should fail.
     std::string cfg_txt = "777";
     ElementPtr config_element = Element::fromJSON(cfg_txt);
 
     // Create the parser.
-    ASSERT_NO_THROW(parser.reset(new ExpressionParser("", parsed_expr,
-                                                      context)));
-    // Expressionn build() should fail.
-    ASSERT_THROW(parser->build(config_element), DhcpConfigError);
+    ExpressionPtr parsed_expr;
+    ExpressionParser parser;
+
+    // Expression parsing should fail.
+    ASSERT_THROW(parser.parse(parsed_expr, config_element, AF_INET6),
+                 DhcpConfigError);
 }
 
 // Verifies that given an invalid expression with a syntax error,
@@ -245,19 +233,31 @@ TEST_F(ExpressionParserTest, invalidExpressionElement) {
 // It is simply to ensure that if the parser fails, it does so
 // Properly.
 TEST_F(ExpressionParserTest, expressionSyntaxError) {
-    ParserContextPtr context(new ParserContext(Option::V4));
-    ExpressionParserPtr parser;
-    ExpressionPtr parsed_expr;
-
     // Turn config into elements.
     std::string cfg_txt = "\"option 'bogus'\"";
     ElementPtr config_element = Element::fromJSON(cfg_txt);
 
     // Create the parser.
-    ASSERT_NO_THROW(parser.reset(new ExpressionParser("", parsed_expr,
-                                                      context)));
-    // Expressionn build() should fail.
-    ASSERT_THROW(parser->build(config_element), DhcpConfigError);
+    ExpressionPtr parsed_expr;
+    ExpressionParser parser;
+
+    // Expression parsing should fail.
+    ASSERT_THROW(parser.parse(parsed_expr, config_element, AF_INET),
+                 DhcpConfigError);
+}
+
+// Verifies that the name parameter is required and must not be empty
+TEST_F(ExpressionParserTest, nameEmpty) {
+    std::string cfg_txt = "{ \"name\": \"\" }";
+    ElementPtr config_element = Element::fromJSON(cfg_txt);
+
+    // Create the parser.
+    ExpressionPtr parsed_expr;
+    ExpressionParser parser;
+
+    // Expression parsing should fail.
+    ASSERT_THROW(parser.parse(parsed_expr, config_element, AF_INET6),
+                 DhcpConfigError);
 }
 
 // Verifies you can create a class with only a name
@@ -270,7 +270,7 @@ TEST_F(ClientClassDefParserTest, nameOnlyValid) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -292,6 +292,7 @@ TEST_F(ClientClassDefParserTest, nameOnlyValid) {
 
 // Verifies you can create a class with a name, expression,
 // but no options.
+// @todo same with AF_INET6
 TEST_F(ClientClassDefParserTest, nameAndExpressionClass) {
 
     std::string cfg_text =
@@ -301,7 +302,7 @@ TEST_F(ClientClassDefParserTest, nameAndExpressionClass) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -333,6 +334,7 @@ TEST_F(ClientClassDefParserTest, nameAndExpressionClass) {
 
 // Verifies you can create a class with a name and options,
 // but no expression.
+// @todo same with AF_INET6
 TEST_F(ClientClassDefParserTest, nameAndOptionsClass) {
 
     std::string cfg_text =
@@ -350,7 +352,7 @@ TEST_F(ClientClassDefParserTest, nameAndOptionsClass) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -368,6 +370,7 @@ TEST_F(ClientClassDefParserTest, nameAndOptionsClass) {
 
 // Verifies you can create a class with a name, expression,
 // and options.
+// @todo same with AF_INET6
 TEST_F(ClientClassDefParserTest, basicValidClass) {
 
     std::string cfg_text =
@@ -386,7 +389,7 @@ TEST_F(ClientClassDefParserTest, basicValidClass) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -429,7 +432,7 @@ TEST_F(ClientClassDefParserTest, noClassName) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
 }
 
@@ -452,7 +455,7 @@ TEST_F(ClientClassDefParserTest, blankClassName) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
 }
 
@@ -466,7 +469,7 @@ TEST_F(ClientClassDefParserTest, unknownElement) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
 }
 
@@ -479,7 +482,7 @@ TEST_F(ClientClassDefParserTest, invalidExpression) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET6),
                  DhcpConfigError);
 }
 
@@ -494,7 +497,7 @@ TEST_F(ClientClassDefParserTest, invalidOptionData) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
 }
 
@@ -516,7 +519,7 @@ TEST_F(ClientClassDefListParserTest, simpleValidList) {
 
     // Parsing the list should succeed.
     ClientClassDictionaryPtr dictionary;
-    ASSERT_NO_THROW(dictionary = parseClientClassDefList(cfg_text, Option::V4));
+    ASSERT_NO_THROW(dictionary = parseClientClassDefList(cfg_text, AF_INET6));
     ASSERT_TRUE(dictionary);
 
     // We should have three classes in the dictionary.
@@ -539,13 +542,6 @@ TEST_F(ClientClassDefListParserTest, simpleValidList) {
     // For good measure, make sure we can't find a non-existant class.
     ASSERT_NO_THROW(cclass = dictionary->findClass("bogus"));
     EXPECT_FALSE(cclass);
-
-    // Verify that the dictionary was pushed to the CfgMgr's staging config.
-    SrvConfigPtr staging = CfgMgr::instance().getStagingCfg();
-    ASSERT_TRUE(staging);
-    ClientClassDictionaryPtr staged_dictionary = staging->getClientClassDictionary();
-    ASSERT_TRUE(staged_dictionary);
-    EXPECT_TRUE(*staged_dictionary == *dictionary);
 }
 
 // Verifies that class list containing a duplicate class entries, fails
@@ -565,7 +561,7 @@ TEST_F(ClientClassDefListParserTest, duplicateClass) {
         "] \n";
 
     ClientClassDictionaryPtr dictionary;
-    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, Option::V4),
+    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, AF_INET),
                  DhcpConfigError);
 }
 
@@ -581,12 +577,13 @@ TEST_F(ClientClassDefListParserTest, invalidClass) {
         "] \n";
 
     ClientClassDictionaryPtr dictionary;
-    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, Option::V4),
+    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, AF_INET6),
                  DhcpConfigError);
 }
 
 // Test verifies that without any class specified, the fixed fields have their
 // default, empty value.
+// @todo same with AF_INET6
 TEST_F(ClientClassDefParserTest, noFixedFields) {
 
     std::string cfg_text =
@@ -601,7 +598,7 @@ TEST_F(ClientClassDefParserTest, noFixedFields) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -629,7 +626,7 @@ TEST_F(ClientClassDefParserTest, nextServer) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -666,8 +663,8 @@ TEST_F(ClientClassDefParserTest, nextServerBogus) {
         "      ] \n"
         "} \n";
 
-    EXPECT_THROW(parseClientClassDef(bogus_v6, Option::V4), DhcpConfigError);
-    EXPECT_THROW(parseClientClassDef(bogus_junk, Option::V4), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(bogus_v6, AF_INET), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(bogus_junk, AF_INET), DhcpConfigError);
 }
 
 // Test verifies that it is possible to define server-hostname field and it
@@ -687,7 +684,7 @@ TEST_F(ClientClassDefParserTest, serverName) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -714,7 +711,7 @@ TEST_F(ClientClassDefParserTest, serverNameInvalid) {
         "      ] \n"
         "} \n";
 
-    EXPECT_THROW(parseClientClassDef(cfg_too_long, Option::V4), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(cfg_too_long, AF_INET), DhcpConfigError);
 }
 
 
@@ -735,7 +732,7 @@ TEST_F(ClientClassDefParserTest, filename) {
         "} \n";
 
     ClientClassDefPtr cclass;
-    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, Option::V4));
+    ASSERT_NO_THROW(cclass = parseClientClassDef(cfg_text, AF_INET));
 
     // We should find our class.
     ASSERT_TRUE(cclass);
@@ -767,7 +764,7 @@ TEST_F(ClientClassDefParserTest, filenameBogus) {
         "      ] \n"
         "} \n";
 
-    EXPECT_THROW(parseClientClassDef(cfg_too_long, Option::V4), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(cfg_too_long, AF_INET), DhcpConfigError);
 }