Browse Source

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

Francis Dupont 8 years ago
parent
commit
fa41a74a7c

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


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

@@ -40,7 +40,7 @@
 #ifndef YY_PARSER4_DHCP4_PARSER_H_INCLUDED
 #ifndef YY_PARSER4_DHCP4_PARSER_H_INCLUDED
 # define YY_PARSER4_DHCP4_PARSER_H_INCLUDED
 # define YY_PARSER4_DHCP4_PARSER_H_INCLUDED
 // //                    "%code requires" blocks.
 // //                    "%code requires" blocks.
-#line 17 "dhcp4_parser.yy" // lalr1.cc:377
+#line 17 "dhcp4_parser.yy" // lalr1.cc:392
 
 
 #include <string>
 #include <string>
 #include <cc/data.h>
 #include <cc/data.h>
@@ -52,7 +52,7 @@ using namespace isc::dhcp;
 using namespace isc::data;
 using namespace isc::data;
 using namespace std;
 using namespace std;
 
 
-#line 56 "dhcp4_parser.h" // lalr1.cc:377
+#line 56 "dhcp4_parser.h" // lalr1.cc:392
 
 
 # include <cassert>
 # include <cassert>
 # include <cstdlib> // std::abort
 # include <cstdlib> // std::abort
@@ -135,9 +135,9 @@ using namespace std;
 # endif /* ! defined YYDEBUG */
 # endif /* ! defined YYDEBUG */
 #endif  /* ! defined PARSER4_DEBUG */
 #endif  /* ! defined PARSER4_DEBUG */
 
 
-#line 14 "dhcp4_parser.yy" // lalr1.cc:377
+#line 14 "dhcp4_parser.yy" // lalr1.cc:392
 namespace isc { namespace dhcp {
 namespace isc { namespace dhcp {
-#line 141 "dhcp4_parser.h" // lalr1.cc:377
+#line 141 "dhcp4_parser.h" // lalr1.cc:392
 
 
 
 
 
 
@@ -1159,8 +1159,8 @@ namespace isc { namespace dhcp {
     enum
     enum
     {
     {
       yyeof_ = 0,
       yyeof_ = 0,
-      yylast_ = 624,     ///< Last index in yytable_.
-      yynnts_ = 267,  ///< Number of nonterminal symbols.
+      yylast_ = 628,     ///< Last index in yytable_.
+      yynnts_ = 269,  ///< Number of nonterminal symbols.
       yyfinal_ = 22, ///< Termination state number.
       yyfinal_ = 22, ///< Termination state number.
       yyterror_ = 1,
       yyterror_ = 1,
       yyerrcode_ = 256,
       yyerrcode_ = 256,
@@ -2118,9 +2118,9 @@ namespace isc { namespace dhcp {
   }
   }
 
 
 
 
-#line 14 "dhcp4_parser.yy" // lalr1.cc:377
+#line 14 "dhcp4_parser.yy" // lalr1.cc:392
 } } // isc::dhcp
 } } // isc::dhcp
-#line 2124 "dhcp4_parser.h" // lalr1.cc:377
+#line 2124 "dhcp4_parser.h" // lalr1.cc:392
 
 
 
 
 
 

+ 25 - 11
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
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -260,14 +260,6 @@ list_generic: LSQUARE_BRACKET {
     // list parsing complete. Put any sanity checking here
     // 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
 list_content: %empty // Empty list
             | not_empty_list
             | not_empty_list
             ;
             ;
@@ -282,6 +274,28 @@ not_empty_list: value {
                   }
                   }
               ;
               ;
 
 
+// This one is used in syntax parser and is restricted to strings.
+list_strings: LSQUARE_BRACKET {
+    // List parsing about to start
+} list_strings_content RSQUARE_BRACKET {
+    // list parsing complete. Put any sanity checking here
+    //ctx.stack_.pop_back();
+};
+
+list_strings_content: %empty // Empty list
+                    | not_empty_list_strings
+                    ;
+
+not_empty_list_strings: STRING {
+                          ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      | not_empty_list_strings COMMA STRING {
+                          ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      ;
+
 // ---- generic JSON parser ends here ----------------------------------
 // ---- generic JSON parser ends here ----------------------------------
 
 
 // ---- syntax checking parser starts here -----------------------------
 // ---- syntax checking parser starts here -----------------------------
@@ -438,7 +452,7 @@ interfaces_list: INTERFACES {
     ctx.stack_.back()->set("interfaces", l);
     ctx.stack_.back()->set("interfaces", l);
     ctx.stack_.push_back(l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };
@@ -1213,7 +1227,7 @@ reservation_client_classes: CLIENT_CLASSES {
     ctx.stack_.back()->set("client-classes", c);
     ctx.stack_.back()->set("client-classes", c);
     ctx.stack_.push_back(c);
     ctx.stack_.push_back(c);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };

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

@@ -441,8 +441,7 @@ DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
     // control-socket has been converted to SimpleParser already.
     // control-socket has been converted to SimpleParser already.
     } else if (config_id.compare("expired-leases-processing") == 0) {
     } else if (config_id.compare("expired-leases-processing") == 0) {
         parser = new ExpirationConfigParser();
         parser = new ExpirationConfigParser();
-    } else if (config_id.compare("client-classes") == 0) {
-        parser = new ClientClassDefListParser(config_id, globalContext());
+    // client-classes has been converted to SimpleParser already.
     // host-reservation-identifiers have been converted to SimpleParser already.
     // host-reservation-identifiers have been converted to SimpleParser already.
     } else {
     } else {
         isc_throw(DhcpConfigError,
         isc_throw(DhcpConfigError,
@@ -573,7 +572,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
     ParserPtr subnet_parser;
     ParserPtr subnet_parser;
     ParserPtr iface_parser;
     ParserPtr iface_parser;
     ParserPtr leases_parser;
     ParserPtr leases_parser;
-    ParserPtr client_classes_parser;
 
 
     // Some of the parsers alter the state of the system in a way that can't
     // 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
     // easily be undone. (Or alter it in a way such that undoing the change has
@@ -646,6 +644,13 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
                 continue;
                 continue;
             }
             }
 
 
+
+            if (config_pair.first == "client-classes") {
+                ClientClassDefListParser parser;
+                parser.parse(config_pair.second, AF_INET);
+                continue;
+            }
+
             ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
             ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
                                                            config_pair.second));
                                                            config_pair.second));
             LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
             LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
@@ -665,8 +670,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
                 // but defer the commit until everything else has committed.
                 // but defer the commit until everything else has committed.
                 hooks_parser = parser;
                 hooks_parser = parser;
                 parser->build(config_pair.second);
                 parser->build(config_pair.second);
-            } else if (config_pair.first == "client-classes") {
-                client_classes_parser = parser;
             } else {
             } else {
                 // Those parsers should be started before other
                 // Those parsers should be started before other
                 // parsers so we can call build straight away.
                 // parsers so we can call build straight away.
@@ -679,15 +682,6 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
             }
             }
         }
         }
 
 
-        // The class definitions parser is the next one to be run.
-        std::map<std::string, ConstElementPtr>::const_iterator cc_config =
-            values_map.find("client-classes");
-        if (cc_config != values_map.end()) {
-            config_pair.first = "client-classes";
-            client_classes_parser->build(cc_config->second);
-            client_classes_parser->commit();
-        }
-
         // The subnet parser is the next one to be run.
         // The subnet parser is the next one to be run.
         std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
         std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
             values_map.find("subnet4");
             values_map.find("subnet4");

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


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

@@ -40,7 +40,7 @@
 #ifndef YY_PARSER6_DHCP6_PARSER_H_INCLUDED
 #ifndef YY_PARSER6_DHCP6_PARSER_H_INCLUDED
 # define YY_PARSER6_DHCP6_PARSER_H_INCLUDED
 # define YY_PARSER6_DHCP6_PARSER_H_INCLUDED
 // //                    "%code requires" blocks.
 // //                    "%code requires" blocks.
-#line 17 "dhcp6_parser.yy" // lalr1.cc:377
+#line 17 "dhcp6_parser.yy" // lalr1.cc:392
 
 
 #include <string>
 #include <string>
 #include <cc/data.h>
 #include <cc/data.h>
@@ -52,7 +52,7 @@ using namespace isc::dhcp;
 using namespace isc::data;
 using namespace isc::data;
 using namespace std;
 using namespace std;
 
 
-#line 56 "dhcp6_parser.h" // lalr1.cc:377
+#line 56 "dhcp6_parser.h" // lalr1.cc:392
 
 
 # include <cassert>
 # include <cassert>
 # include <cstdlib> // std::abort
 # include <cstdlib> // std::abort
@@ -135,9 +135,9 @@ using namespace std;
 # endif /* ! defined YYDEBUG */
 # endif /* ! defined YYDEBUG */
 #endif  /* ! defined PARSER6_DEBUG */
 #endif  /* ! defined PARSER6_DEBUG */
 
 
-#line 14 "dhcp6_parser.yy" // lalr1.cc:377
+#line 14 "dhcp6_parser.yy" // lalr1.cc:392
 namespace isc { namespace dhcp {
 namespace isc { namespace dhcp {
-#line 141 "dhcp6_parser.h" // lalr1.cc:377
+#line 141 "dhcp6_parser.h" // lalr1.cc:392
 
 
 
 
 
 
@@ -1164,8 +1164,8 @@ namespace isc { namespace dhcp {
     enum
     enum
     {
     {
       yyeof_ = 0,
       yyeof_ = 0,
-      yylast_ = 630,     ///< Last index in yytable_.
-      yynnts_ = 271,  ///< Number of nonterminal symbols.
+      yylast_ = 638,     ///< Last index in yytable_.
+      yynnts_ = 273,  ///< Number of nonterminal symbols.
       yyfinal_ = 24, ///< Termination state number.
       yyfinal_ = 24, ///< Termination state number.
       yyterror_ = 1,
       yyterror_ = 1,
       yyerrcode_ = 256,
       yyerrcode_ = 256,
@@ -2129,9 +2129,9 @@ namespace isc { namespace dhcp {
   }
   }
 
 
 
 
-#line 14 "dhcp6_parser.yy" // lalr1.cc:377
+#line 14 "dhcp6_parser.yy" // lalr1.cc:392
 } } // isc::dhcp
 } } // isc::dhcp
-#line 2135 "dhcp6_parser.h" // lalr1.cc:377
+#line 2135 "dhcp6_parser.h" // lalr1.cc:392
 
 
 
 
 
 

+ 30 - 14
src/bin/dhcp6/dhcp6_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
    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -261,14 +261,6 @@ list_generic: LSQUARE_BRACKET {
     // list parsing complete. Put any sanity checking here
     // 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
 list_content: %empty // Empty list
             | not_empty_list
             | not_empty_list
             ;
             ;
@@ -283,6 +275,28 @@ not_empty_list: value {
                   }
                   }
               ;
               ;
 
 
+// This one is used in syntax parser and is restricted to strings.
+list_strings: LSQUARE_BRACKET {
+    // List parsing about to start
+} list_strings_content RSQUARE_BRACKET {
+    // list parsing complete. Put any sanity checking here
+    //ctx.stack_.pop_back();
+};
+
+list_strings_content: %empty // Empty list
+                    | not_empty_list_strings
+                    ;
+
+not_empty_list_strings: STRING {
+                          ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      | not_empty_list_strings COMMA STRING {
+                          ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
+                          ctx.stack_.back()->add(s);
+                          }
+                      ;
+
 // ---- generic JSON parser ends here ----------------------------------
 // ---- generic JSON parser ends here ----------------------------------
 
 
 // ---- syntax checking parser starts here -----------------------------
 // ---- syntax checking parser starts here -----------------------------
@@ -425,7 +439,7 @@ interface_config_map: INTERFACES {
     ctx.stack_.back()->set("interfaces", l);
     ctx.stack_.back()->set("interfaces", l);
     ctx.stack_.push_back(l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };
@@ -571,12 +585,14 @@ hw_address_id : HW_ADDRESS {
     ctx.stack_.back()->add(hwaddr);
     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 {
 relay_supplied_options: RELAY_SUPPLIED_OPTIONS {
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
     ElementPtr l(new ListElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("relay-supplied-options", l);
     ctx.stack_.back()->set("relay-supplied-options", l);
     ctx.stack_.push_back(l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON LSQUARE_BRACKET list_content RSQUARE_BRACKET {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };
@@ -1192,7 +1208,7 @@ ip_addresses: IP_ADDRESSES {
     ctx.stack_.back()->set("ip-addresses", l);
     ctx.stack_.back()->set("ip-addresses", l);
     ctx.stack_.push_back(l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };
@@ -1202,7 +1218,7 @@ prefixes: PREFIXES  {
     ctx.stack_.back()->set("prefixes", l);
     ctx.stack_.back()->set("prefixes", l);
     ctx.stack_.push_back(l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };
@@ -1236,7 +1252,7 @@ reservation_client_classes: CLIENT_CLASSES {
     ctx.stack_.back()->set("client-classes", c);
     ctx.stack_.back()->set("client-classes", c);
     ctx.stack_.push_back(c);
     ctx.stack_.push_back(c);
     ctx.enter(ctx.NO_KEYWORD);
     ctx.enter(ctx.NO_KEYWORD);
-} COLON list2 {
+} COLON list_strings {
     ctx.stack_.pop_back();
     ctx.stack_.pop_back();
     ctx.leave();
     ctx.leave();
 };
 };

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

@@ -722,8 +722,7 @@ DhcpConfigParser* createGlobal6DhcpConfigParser(const std::string& config_id,
     // control-socket has been converted to SimpleParser.
     // control-socket has been converted to SimpleParser.
     } else if (config_id.compare("expired-leases-processing") == 0) {
     } else if (config_id.compare("expired-leases-processing") == 0) {
         parser = new ExpirationConfigParser();
         parser = new ExpirationConfigParser();
-    } else if (config_id.compare("client-classes") == 0) {
-        parser = new ClientClassDefListParser(config_id, globalContext());
+    // client-classes has been converted to SimpleParser.
     } else if (config_id.compare("server-id") == 0) {
     } else if (config_id.compare("server-id") == 0) {
         parser = new DUIDConfigParser();
         parser = new DUIDConfigParser();
     // host-reservation-identifiers have been converted to SimpleParser already.
     // host-reservation-identifiers have been converted to SimpleParser already.
@@ -845,7 +844,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
     ParserPtr subnet_parser;
     ParserPtr subnet_parser;
     ParserPtr iface_parser;
     ParserPtr iface_parser;
     ParserPtr leases_parser;
     ParserPtr leases_parser;
-    ParserPtr client_classes_parser;
 
 
     // Some of the parsers alter state of the system that can't easily
     // 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
     // be undone. (Or alter it in a way such that undoing the change
@@ -925,6 +923,12 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
                 continue;
                 continue;
             }
             }
 
 
+	    if (config_pair.first =="client-classes") {
+		ClientClassDefListParser parser;
+		parser.parse(config_pair.second, AF_INET6);
+		continue;
+	    }
+
             ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
             ParserPtr parser(createGlobal6DhcpConfigParser(config_pair.first,
                                                            config_pair.second));
                                                            config_pair.second));
             LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
             LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PARSER_CREATED)
@@ -945,8 +949,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
                 // can be run here before other parsers.
                 // can be run here before other parsers.
                 parser->build(config_pair.second);
                 parser->build(config_pair.second);
                 iface_parser = parser;
                 iface_parser = parser;
-            } else if (config_pair.first == "client-classes") {
-                client_classes_parser = parser;
             } else {
             } else {
                 // Those parsers should be started before other
                 // Those parsers should be started before other
                 // parsers so we can call build straight away.
                 // parsers so we can call build straight away.
@@ -959,15 +961,6 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set) {
             }
             }
         }
         }
 
 
-        // The class definitions parser is the next one to be run.
-        std::map<std::string, ConstElementPtr>::const_iterator cc_config =
-            values_map.find("client-classes");
-        if (cc_config != values_map.end()) {
-            config_pair.first = "client-classes";
-            client_classes_parser->build(cc_config->second);
-            client_classes_parser->commit();
-        }
-
         // The subnet parser is the next one to be run.
         // The subnet parser is the next one to be run.
         std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
         std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
             values_map.find("subnet6");
             values_map.find("subnet6");

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

+ 27 - 66
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
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7,10 +7,11 @@
 #ifndef CLIENT_CLASS_DEF_PARSER_H
 #ifndef CLIENT_CLASS_DEF_PARSER_H
 #define 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/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
 /// @brief Parsers for client class definitions
 ///
 ///
@@ -22,11 +23,10 @@
 /// There parsers defined are:
 /// There parsers defined are:
 ///
 ///
 /// ClientClassDefListParser  - creates a ClientClassDictionary from a list
 /// 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
 /// single class.  The names of the classes in the are expected to be
 /// unique.  Attempting to define a duplicate class will result in an
 /// 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
 /// ClientClassDefParser - creates a ClientClassDefinition from an element
 /// map. The elements are as follows:
 /// map. The elements are as follows:
@@ -37,7 +37,7 @@
 /// membership in the class. This is passed into the eval parser.
 /// membership in the class. This is passed into the eval parser.
 ///
 ///
 /// -# "option-data" - a list which defines the options that should be
 /// -# "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.
 /// using the @ref isc::dhcp::OptionDataListParser.
 ///
 ///
 /// ExpressionParser  - creates an eval::Expression from a string element,
 /// ExpressionParser  - creates an eval::Expression from a string element,
@@ -51,27 +51,20 @@ namespace dhcp {
 /// This parser creates an instance of an Expression from a string.  The
 /// This parser creates an instance of an Expression from a string.  The
 /// string is passed to the Eval Parser and the resultant Expression is
 /// string is passed to the Eval Parser and the resultant Expression is
 /// stored into the ExpressionPtr reference passed into the constructor.
 /// stored into the ExpressionPtr reference passed into the constructor.
-class ExpressionParser : public DhcpConfigParser {
+class ExpressionParser : public isc::data::SimpleParser {
 public:
 public:
     /// @brief Constructor.
     /// @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 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);
+    ExpressionParser(ExpressionPtr& expression);
 
 
     /// @brief Parses an expression configuration element into an Expression
     /// @brief Parses an expression configuration element into an Expression
     ///
     ///
     /// @param expression_cfg the configuration entry to be parsed.
     /// @param expression_cfg the configuration entry to be parsed.
+    /// @param family the address family of the expression.
     ///
     ///
     /// @throw DhcpConfigError if parsing was unsuccessful.
     /// @throw DhcpConfigError if parsing was unsuccessful.
-    void build(isc::data::ConstElementPtr expression_cfg);
-
-    /// @brief Stores the parsed expression to the supplied storage.
-    void commit();
+    void parse(isc::data::ConstElementPtr expression_cfg, uint16_t family);
 
 
 private:
 private:
     /// @brief Local storage for the parsed expression
     /// @brief Local storage for the parsed expression
@@ -79,47 +72,30 @@ private:
 
 
     /// @brief Storage into which the parsed expression should be committed
     /// @brief Storage into which the parsed expression should be committed
     ExpressionPtr& expression_;
     ExpressionPtr& expression_;
-
-    /// @brief Parsing context which contains global values, options and option
-    /// definitions.
-    ParserContextPtr global_context_;
 };
 };
 
 
-typedef boost::shared_ptr<ExpressionParser> ExpressionParserPtr;
-
 /// @brief Parser for a single client class definition.
 /// @brief Parser for a single client class definition.
 ///
 ///
 /// This parser creates an instance of a client class definition.
 /// This parser creates an instance of a client class definition.
-class ClientClassDefParser : public DhcpConfigParser {
+class ClientClassDefParser : public isc::data::SimpleParser {
 public:
 public:
     /// @brief Constructor.
     /// @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 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);
+    ClientClassDefParser(ClientClassDictionaryPtr& class_dictionary);
 
 
     /// @brief Parses an entry that describes single client class definition.
     /// @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().
     /// This done here to detect duplicate classes prior to commit().
     /// @param client_class_def a configuration entry to be parsed.
     /// @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.
     /// @throw DhcpConfigError if parsing was unsuccessful.
-    void build(isc::data::ConstElementPtr client_class_def);
-
-    /// @brief Does nothing.
-    void commit() {};
+    void parse(isc::data::ConstElementPtr client_class_def, uint16_t family);
 
 
 private:
 private:
 
 
-    /// @brief Storage for class string values.
-    StringStoragePtr string_values_;
-
     /// @brief Storage for the class match expression
     /// @brief Storage for the class match expression
     ExpressionPtr match_expr_;
     ExpressionPtr match_expr_;
 
 
@@ -127,11 +103,7 @@ private:
     CfgOptionPtr options_;
     CfgOptionPtr options_;
 
 
     /// @brief Dictionary to which the new class should be added
     /// @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_;
+    ClientClassDictionaryPtr& class_dictionary_;
 };
 };
 
 
 /// @brief Defines a pointer to a ClientClassDefParser
 /// @brief Defines a pointer to a ClientClassDefParser
@@ -141,44 +113,33 @@ typedef boost::shared_ptr<ClientClassDefParser> ClientClassDefParserPtr;
 ///
 ///
 /// This parser iterates over all configuration entries that define
 /// This parser iterates over all configuration entries that define
 /// client classes and creates ClientClassDef instances for each.
 /// 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.
 /// created definitions is given to the CfgMgr.
-class ClientClassDefListParser : public DhcpConfigParser {
+class ClientClassDefListParser : public isc::data::SimpleParser {
 public:
 public:
+
     /// @brief Constructor.
     /// @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);
+    ClientClassDefListParser();
 
 
     /// @brief Parse configuration entries.
     /// @brief Parse configuration entries.
     ///
     ///
     /// This function parses configuration entries, creates instances
     /// This function parses configuration entries, creates instances
     /// of client class definitions and tries to adds them to the a
     /// of client class definitions and tries to adds them to the a
-    /// local dictionary.
+    /// local dictionary. At the end class definitions are committed
+    /// to CfgMgr's global storage.
     ///
     ///
     /// @param class_def_list pointer to an element that holds entries
     /// @param class_def_list pointer to an element that holds entries
     /// for client class definitions.
     /// for client class definitions.
+    /// @param family the address family of the client class definitions.
     /// @throw DhcpConfigError if configuration parsing fails.
     /// @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();
+    void parse(isc::data::ConstElementPtr class_def_list, uint16_t family);
 
 
     /// @brief Local class dictionary to store classes as they are being parsed
     /// @brief Local class dictionary to store classes as they are being parsed
+    ///
+    /// Left public for easier unit testing.
     ClientClassDictionaryPtr local_dictionary_;
     ClientClassDictionaryPtr local_dictionary_;
-
-    /// Parsing context which contains global values, options and option
-    /// definitions.
-    ParserContextPtr global_context_;
 };
 };
 
 
-/// @brief Defines a pointer to a ClientClassDefListParser
-typedef boost::shared_ptr<ClientClassDefListParser> ClientClassDefListParserPtr;
-
 } // end of namespace isc::dhcp
 } // end of namespace isc::dhcp
 } // end of namespace isc
 } // end of namespace isc
 
 

+ 60 - 73
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
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -12,6 +12,7 @@
 #include <dhcp/option_string.h>
 #include <dhcp/option_string.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
 #include <asiolink/io_address.h>
 #include <asiolink/io_address.h>
 #include <eval/evaluate.h>
 #include <eval/evaluate.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
@@ -39,35 +40,30 @@ protected:
     /// produces an Expression which can be evaluated against a v4 or v6
     /// produces an Expression which can be evaluated against a v4 or v6
     /// packet.
     /// packet.
     ///
     ///
-    /// @param universe V4 or V6.
+    /// @param family AF_INET or AF_INET6
     /// @param expression Textual representation of the expression to be
     /// @param expression Textual representation of the expression to be
     /// evaluated.
     /// evaluated.
     /// @param option_string String data to be placed in the hostname
     /// @param option_string String data to be placed in the hostname
     /// option, being placed in the packet used for evaluation.
     /// option, being placed in the packet used for evaluation.
     /// @tparam Type of the packet: @c Pkt4 or @c Pkt6.
     /// @tparam Type of the packet: @c Pkt4 or @c Pkt6.
     template<typename PktType>
     template<typename PktType>
-    void testValidExpression(const Option::Universe& universe,
+    void testValidExpression(uint16_t family,
                              const std::string& expression,
                              const std::string& expression,
                              const std::string& option_string) {
                              const std::string& option_string) {
-        ParserContextPtr context(new ParserContext(universe));
-        ExpressionParserPtr parser;
         ExpressionPtr parsed_expr;
         ExpressionPtr parsed_expr;
+        ExpressionParser parser(parsed_expr);
 
 
         // Turn config into elements.  This may emit exceptions.
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(expression);
         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(config_element, family));
 
 
         // Parsed expression should exist.
         // Parsed expression should exist.
         ASSERT_TRUE(parsed_expr);
         ASSERT_TRUE(parsed_expr);
 
 
         // Build a packet that will fail evaluation.
         // 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,
                                                    DHCPDISCOVER : DHCPV6_SOLICIT,
                                                    123));
                                                    123));
         EXPECT_FALSE(evaluate(*parsed_expr, *pkt));
         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
         // 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
         // single string value, i.e. hostname for DHCPv4 and bootfile url for
         // DHCPv6.
         // 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,
                                        DHO_HOST_NAME : D6O_BOOTFILE_URL,
                                        option_string));
                                        option_string));
         pkt->addOption(opt);
         pkt->addOption(opt);
@@ -93,25 +90,23 @@ protected:
     ///
     ///
     /// @param config - JSON string containing the client class configuration
     /// @param config - JSON string containing the client class configuration
     /// to parse.
     /// to parse.
-    /// @param universe - the universe in which the parsing context should
+    /// @param family - the address family in which the parsing should
     /// occur.
     /// occur.
     /// @return Returns a pointer to class instance created, or NULL if
     /// @return Returns a pointer to class instance created, or NULL if
     /// for some unforeseen reason it wasn't created in the local dictionary
     /// for some unforeseen reason it wasn't created in the local dictionary
     /// @throw indirectly, exceptions convertring the JSON text to elements,
     /// @throw indirectly, exceptions convertring the JSON text to elements,
     /// or by the parsing itself are not caught
     /// or by the parsing itself are not caught
     ClientClassDefPtr parseClientClassDef(const std::string& config,
     ClientClassDefPtr parseClientClassDef(const std::string& config,
-                                          Option::Universe universe) {
+                                          uint16_t family) {
         // Create local dicitonary to which the parser add the class.
         // Create local dicitonary to which the parser add the class.
         ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
         ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
-        // Create the "global" context for the parser.
-        ParserContextPtr context(new ParserContext(universe));
 
 
         // Turn config into elements.  This may emit exceptions.
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(config);
         ElementPtr config_element = Element::fromJSON(config);
 
 
         // Parse the configuration. This may emit exceptions.
         // Parse the configuration. This may emit exceptions.
-        ClientClassDefParser parser("", dictionary, context);
-        parser.build(config_element);
+        ClientClassDefParser parser(dictionary);
+        parser.parse(config_element, family);
 
 
         // If we didn't throw, then return the first and only class
         // If we didn't throw, then return the first and only class
         ClientClassDefMapPtr classes = dictionary->getClasses();
         ClientClassDefMapPtr classes = dictionary->getClasses();
@@ -136,26 +131,20 @@ protected:
     /// ClientClassDictionary.
     /// ClientClassDictionary.
     ///
     ///
     /// @param config - JSON string containing the list of definitions to parse.
     /// @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.
     /// occur.
     /// @return Returns a pointer to class dictionary created
     /// @return Returns a pointer to class dictionary created
     /// @throw indirectly, execptions convertring the JSON text to elements,
     /// @throw indirectly, execptions convertring the JSON text to elements,
     /// or by the parsing itself are not caught
     /// or by the parsing itself are not caught
     ClientClassDictionaryPtr parseClientClassDefList(const std::string& config,
     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.
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(config);
         ElementPtr config_element = Element::fromJSON(config);
 
 
         // Parse the configuration. This may emit exceptions.
         // Parse the configuration. This may emit exceptions.
-        ClientClassDefListParser parser("", context);
-        parser.build(config_element);
-
-        // Commit should push it to CfgMgr staging
-        parser.commit();
+        ClientClassDefListParser parser;
+        parser.parse(config_element, family);
 
 
         // Return the parser's local dicationary
         // Return the parser's local dicationary
         return (parser.local_dictionary_);
         return (parser.local_dictionary_);
@@ -165,13 +154,14 @@ protected:
 // Verifies that given a valid expression, the ExpressionParser
 // Verifies that given a valid expression, the ExpressionParser
 // produces an Expression which can be evaluated against a v4 packet.
 // produces an Expression which can be evaluated against a v4 packet.
 TEST_F(ExpressionParserTest, validExpression4) {
 TEST_F(ExpressionParserTest, validExpression4) {
-    testValidExpression<Pkt4>(Option::V4, "\"option[12].text == 'hundred4'\"",
+    testValidExpression<Pkt4>(AF_INET,
+                              "\"option[12].text == 'hundred4'\"",
                               "hundred4");
                               "hundred4");
 }
 }
 
 
 // Verifies that the option name can be used in the evaluated expression.
 // Verifies that the option name can be used in the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionName4) {
 TEST_F(ExpressionParserTest, validExpressionWithOptionName4) {
-    testValidExpression<Pkt4>(Option::V4,
+    testValidExpression<Pkt4>(AF_INET,
                               "\"option[host-name].text == 'hundred4'\"",
                               "\"option[host-name].text == 'hundred4'\"",
                               "hundred4");
                               "hundred4");
 }
 }
@@ -180,14 +170,15 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName4) {
 // ExpressionParser produces an Expression which can be evaluated against
 // ExpressionParser produces an Expression which can be evaluated against
 // a v4 packet.
 // a v4 packet.
 TEST_F(ExpressionParserTest, validExpressionWithHex4) {
 TEST_F(ExpressionParserTest, validExpressionWithHex4) {
-    testValidExpression<Pkt4>(Option::V4, "\"option[12].hex == 0x68756E6472656434\"",
+    testValidExpression<Pkt4>(AF_INET,
+                              "\"option[12].hex == 0x68756E6472656434\"",
                               "hundred4");
                               "hundred4");
 }
 }
 
 
 // Verifies that the option name can be used together with .hex operator in
 // Verifies that the option name can be used together with .hex operator in
 // the evaluated expression.
 // the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) {
 TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) {
-    testValidExpression<Pkt6>(Option::V4,
+    testValidExpression<Pkt6>(AF_INET,
                               "\"option[host-name].text == 0x68756E6472656434\"",
                               "\"option[host-name].text == 0x68756E6472656434\"",
                               "hundred4");
                               "hundred4");
 }
 }
@@ -195,13 +186,14 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex4) {
 // Verifies that given a valid expression, the ExpressionParser
 // Verifies that given a valid expression, the ExpressionParser
 // produces an Expression which can be evaluated against a v6 packet.
 // produces an Expression which can be evaluated against a v6 packet.
 TEST_F(ExpressionParserTest, validExpression6) {
 TEST_F(ExpressionParserTest, validExpression6) {
-    testValidExpression<Pkt6>(Option::V6, "\"option[59].text == 'hundred6'\"",
+    testValidExpression<Pkt6>(AF_INET6,
+                              "\"option[59].text == 'hundred6'\"",
                               "hundred6");
                               "hundred6");
 }
 }
 
 
 // Verifies that the option name can be used in the evaluated expression.
 // Verifies that the option name can be used in the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionName6) {
 TEST_F(ExpressionParserTest, validExpressionWithOptionName6) {
-    testValidExpression<Pkt6>(Option::V6,
+    testValidExpression<Pkt6>(AF_INET6,
                               "\"option[bootfile-url].text == 'hundred6'\"",
                               "\"option[bootfile-url].text == 'hundred6'\"",
                               "hundred6");
                               "hundred6");
 }
 }
@@ -210,33 +202,31 @@ TEST_F(ExpressionParserTest, validExpressionWithOptionName6) {
 // ExpressionParser produces an Expression which can be evaluated against
 // ExpressionParser produces an Expression which can be evaluated against
 // a v6 packet.
 // a v6 packet.
 TEST_F(ExpressionParserTest, validExpressionWithHex6) {
 TEST_F(ExpressionParserTest, validExpressionWithHex6) {
-    testValidExpression<Pkt6>(Option::V6, "\"option[59].hex == 0x68756E6472656436\"",
+    testValidExpression<Pkt6>(AF_INET6,
+                              "\"option[59].hex == 0x68756E6472656436\"",
                               "hundred6");
                               "hundred6");
 }
 }
 
 
 // Verifies that the option name can be used together with .hex operator in
 // Verifies that the option name can be used together with .hex operator in
 // the evaluated expression.
 // the evaluated expression.
 TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex6) {
 TEST_F(ExpressionParserTest, validExpressionWithOptionNameAndHex6) {
-    testValidExpression<Pkt6>(Option::V6,
+    testValidExpression<Pkt6>(AF_INET6,
                               "\"option[bootfile-url].text == 0x68756E6472656436\"",
                               "\"option[bootfile-url].text == 0x68756E6472656436\"",
                               "hundred6");
                               "hundred6");
 }
 }
 
 
 // Verifies that an the ExpressionParser only accepts StringElements.
 // Verifies that an the ExpressionParser only accepts StringElements.
 TEST_F(ExpressionParserTest, invalidExpressionElement) {
 TEST_F(ExpressionParserTest, invalidExpressionElement) {
-    ParserContextPtr context(new ParserContext(Option::V4));
-    ExpressionParserPtr parser;
-    ExpressionPtr parsed_expr;
-
     // This will create an integer element should fail.
     // This will create an integer element should fail.
     std::string cfg_txt = "777";
     std::string cfg_txt = "777";
     ElementPtr config_element = Element::fromJSON(cfg_txt);
     ElementPtr config_element = Element::fromJSON(cfg_txt);
 
 
     // Create the parser.
     // 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(parsed_expr);
+
+    // Expression parsing should fail.
+    ASSERT_THROW(parser.parse(config_element, AF_INET), DhcpConfigError);
 }
 }
 
 
 // Verifies that given an invalid expression with a syntax error,
 // Verifies that given an invalid expression with a syntax error,
@@ -245,19 +235,16 @@ TEST_F(ExpressionParserTest, invalidExpressionElement) {
 // It is simply to ensure that if the parser fails, it does so
 // It is simply to ensure that if the parser fails, it does so
 // Properly.
 // Properly.
 TEST_F(ExpressionParserTest, expressionSyntaxError) {
 TEST_F(ExpressionParserTest, expressionSyntaxError) {
-    ParserContextPtr context(new ParserContext(Option::V4));
-    ExpressionParserPtr parser;
-    ExpressionPtr parsed_expr;
-
     // Turn config into elements.
     // Turn config into elements.
     std::string cfg_txt = "\"option 'bogus'\"";
     std::string cfg_txt = "\"option 'bogus'\"";
     ElementPtr config_element = Element::fromJSON(cfg_txt);
     ElementPtr config_element = Element::fromJSON(cfg_txt);
 
 
     // Create the parser.
     // 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(parsed_expr);
+
+    // Expression parsing should fail.
+    ASSERT_THROW(parser.parse(config_element, AF_INET), DhcpConfigError);
 }
 }
 
 
 // Verifies you can create a class with only a name
 // Verifies you can create a class with only a name
@@ -270,7 +257,7 @@ TEST_F(ClientClassDefParserTest, nameOnlyValid) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -301,7 +288,7 @@ TEST_F(ClientClassDefParserTest, nameAndExpressionClass) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -350,7 +337,7 @@ TEST_F(ClientClassDefParserTest, nameAndOptionsClass) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -386,7 +373,7 @@ TEST_F(ClientClassDefParserTest, basicValidClass) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -429,7 +416,7 @@ TEST_F(ClientClassDefParserTest, noClassName) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -452,7 +439,7 @@ TEST_F(ClientClassDefParserTest, blankClassName) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -466,7 +453,7 @@ TEST_F(ClientClassDefParserTest, unknownElement) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -479,7 +466,7 @@ TEST_F(ClientClassDefParserTest, invalidExpression) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -494,7 +481,7 @@ TEST_F(ClientClassDefParserTest, invalidOptionData) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     ClientClassDefPtr cclass;
-    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, Option::V4),
+    ASSERT_THROW(cclass = parseClientClassDef(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -516,7 +503,7 @@ TEST_F(ClientClassDefListParserTest, simpleValidList) {
 
 
     // Parsing the list should succeed.
     // Parsing the list should succeed.
     ClientClassDictionaryPtr dictionary;
     ClientClassDictionaryPtr dictionary;
-    ASSERT_NO_THROW(dictionary = parseClientClassDefList(cfg_text, Option::V4));
+    ASSERT_NO_THROW(dictionary = parseClientClassDefList(cfg_text, AF_INET));
     ASSERT_TRUE(dictionary);
     ASSERT_TRUE(dictionary);
 
 
     // We should have three classes in the dictionary.
     // We should have three classes in the dictionary.
@@ -565,7 +552,7 @@ TEST_F(ClientClassDefListParserTest, duplicateClass) {
         "] \n";
         "] \n";
 
 
     ClientClassDictionaryPtr dictionary;
     ClientClassDictionaryPtr dictionary;
-    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, Option::V4),
+    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -581,7 +568,7 @@ TEST_F(ClientClassDefListParserTest, invalidClass) {
         "] \n";
         "] \n";
 
 
     ClientClassDictionaryPtr dictionary;
     ClientClassDictionaryPtr dictionary;
-    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, Option::V4),
+    ASSERT_THROW(dictionary = parseClientClassDefList(cfg_text, AF_INET),
                  DhcpConfigError);
                  DhcpConfigError);
 }
 }
 
 
@@ -601,7 +588,7 @@ TEST_F(ClientClassDefParserTest, noFixedFields) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -629,7 +616,7 @@ TEST_F(ClientClassDefParserTest, nextServer) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -666,8 +653,8 @@ TEST_F(ClientClassDefParserTest, nextServerBogus) {
         "      ] \n"
         "      ] \n"
         "} \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
 // Test verifies that it is possible to define server-hostname field and it
@@ -687,7 +674,7 @@ TEST_F(ClientClassDefParserTest, serverName) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -714,7 +701,7 @@ TEST_F(ClientClassDefParserTest, serverNameInvalid) {
         "      ] \n"
         "      ] \n"
         "} \n";
         "} \n";
 
 
-    EXPECT_THROW(parseClientClassDef(cfg_too_long, Option::V4), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(cfg_too_long, AF_INET), DhcpConfigError);
 }
 }
 
 
 
 
@@ -735,7 +722,7 @@ TEST_F(ClientClassDefParserTest, filename) {
         "} \n";
         "} \n";
 
 
     ClientClassDefPtr cclass;
     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.
     // We should find our class.
     ASSERT_TRUE(cclass);
     ASSERT_TRUE(cclass);
@@ -767,7 +754,7 @@ TEST_F(ClientClassDefParserTest, filenameBogus) {
         "      ] \n"
         "      ] \n"
         "} \n";
         "} \n";
 
 
-    EXPECT_THROW(parseClientClassDef(cfg_too_long, Option::V4), DhcpConfigError);
+    EXPECT_THROW(parseClientClassDef(cfg_too_long, AF_INET), DhcpConfigError);
 }
 }