]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1928] Optionally skip checking deps
authorMarcin Siodelski <marcin@isc.org>
Thu, 8 Jul 2021 17:12:13 +0000 (19:12 +0200)
committerMarcin Siodelski <marcin@isc.org>
Wed, 21 Jul 2021 11:03:29 +0000 (13:03 +0200)
The client class parser can be configured to skip checking class
dependencies during parsing.

src/lib/dhcpsrv/parsers/client_class_def_parser.cc
src/lib/dhcpsrv/parsers/client_class_def_parser.h
src/lib/dhcpsrv/tests/client_class_def_parser_unittest.cc

index fb1c2c71080ad3a2784f43393a1f25bfb5063f7f..75a71ca1b71d042dccf74d51bee94cf2be0b5294 100644 (file)
@@ -70,7 +70,8 @@ void
 ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
                             ConstElementPtr class_def_cfg,
                             uint16_t family,
-                            bool append_error_position) {
+                            bool append_error_position,
+                            bool check_dependencies) {
     // name is now mandatory, so let's deal with it first.
     std::string name = getString(class_def_cfg, "name");
     if (name.empty()) {
@@ -87,11 +88,11 @@ ClientClassDefParser::parse(ClientClassDictionaryPtr& class_dictionary,
     if (test_cfg) {
         ExpressionParser parser;
         auto check_defined =
-            [&class_dictionary, &depend_on_known]
+            [&class_dictionary, &depend_on_known, check_dependencies]
             (const ClientClass& cclass) {
-                return (isClientClassDefined(class_dictionary,
-                                             depend_on_known,
-                                             cclass));
+                return (!check_dependencies || isClientClassDefined(class_dictionary,
+                                                                    depend_on_known,
+                                                                    cclass));
         };
         parser.parse(match_expr, test_cfg, family, check_defined);
         test = test_cfg->stringValue();
@@ -282,12 +283,12 @@ ClientClassDefParser::checkParametersSupported(const ConstElementPtr& class_def_
 
 ClientClassDictionaryPtr
 ClientClassDefListParser::parse(ConstElementPtr client_class_def_list,
-                                uint16_t family) {
+                                uint16_t family, bool check_dependencies) {
     ClientClassDictionaryPtr dictionary(new ClientClassDictionary());
     BOOST_FOREACH(ConstElementPtr client_class_def,
                   client_class_def_list->listValue()) {
         ClientClassDefParser parser;
-        parser.parse(dictionary, client_class_def, family);
+        parser.parse(dictionary, client_class_def, family, true, check_dependencies);
     }
     return (dictionary);
 }
index 221ba138501b348bf4344e66c9c45cdf666058ae..a0720d0464273ede488c3bdf9441add21c764326 100644 (file)
@@ -94,12 +94,15 @@ public:
     /// of the parsed string within parsed JSON should be appended. The
     /// default setting is to append it, but it is typically set to false
     /// when this parser is used by hooks libraries.
+    /// @param check_dependencies indicates if the parser should evaluate an
+    /// expression to see if the referenced client classes exist.
     ///
     /// @throw DhcpConfigError if parsing was unsuccessful.
     void parse(ClientClassDictionaryPtr& class_dictionary,
                isc::data::ConstElementPtr client_class_def,
                uint16_t family,
-               bool append_error_position = true);
+               bool append_error_position = true,
+               bool check_dependencies = true);
 
     /// @brief Iterates over class parameters and checks if they are supported.
     ///
@@ -135,10 +138,13 @@ public:
     /// @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.
+    /// @param check_dependencies indicates if the parser should evaluate an
+    /// expression to see if the referenced client classes exist.
     /// @return a pointer to the filled dictionary
     /// @throw DhcpConfigError if configuration parsing fails.
     ClientClassDictionaryPtr
-    parse(isc::data::ConstElementPtr class_def_list, uint16_t family);
+    parse(isc::data::ConstElementPtr class_def_list, uint16_t family,
+          bool check_dependencies = true);
 };
 
 } // end of namespace isc::dhcp
index 495a560a8f4356dc3112d62a5c95f4623448e301..2c6f90105967311918ca1583f6e1436271bf22a1 100644 (file)
@@ -157,18 +157,21 @@ protected:
     /// @param config - JSON string containing the list of definitions to parse.
     /// @param family - the address family in which the parsing should
     /// occur.
+    /// @param check_dependencies - indicates if the parser should check whether
+    /// referenced classes exist.
     /// @return Returns a pointer to class dictionary created
     /// @throw indirectly, exceptions converting the JSON text to elements,
     /// or by the parsing itself are not caught
     ClientClassDictionaryPtr parseClientClassDefList(const std::string& config,
-                                                     uint16_t family)
+                                                     uint16_t family,
+                                                     bool check_dependencies = true)
     {
         // Turn config into elements.  This may emit exceptions.
         ElementPtr config_element = Element::fromJSON(config);
 
         // Parse the configuration. This may emit exceptions.
         ClientClassDefListParser parser;
-        return (parser.parse(config_element, family));
+        return (parser.parse(config_element, family, check_dependencies));
     }
 };
 
@@ -1087,6 +1090,24 @@ TEST_F(ClientClassDefListParserTest, dependentNotDefined) {
     EXPECT_THROW(parseClientClassDefList(cfg_text, AF_INET6), DhcpConfigError);
 }
 
+// Verifies that error is not reported when a class references another
+// not defined class, but dependency checking is disabled.
+TEST_F(ClientClassDefListParserTest, dependencyCheckingDisabled) {
+    std::string cfg_text =
+        "[ \n"
+        "   { \n"
+        "       \"name\": \"one\", \n"
+        "       \"test\": \"member('foo')\" \n"
+        "   } \n"
+        "] \n";
+    try {
+        parseClientClassDefList(cfg_text, AF_INET6, false);
+    } catch ( const std::exception& ex) {
+        std::cout << ex.what() << std::endl;
+    }
+    EXPECT_NO_THROW(parseClientClassDefList(cfg_text, AF_INET6, false));
+}
+
 // Verifies that forward dependencies will not parse.
 TEST_F(ClientClassDefListParserTest, dependentForwardError) {
     std::string cfg_text =