Browse Source

[3436] D2CfgMgr now validates top level params

D2CfgMgr::buildParams now validates all of the
top level params prior to calling the D2Params
constructor.  This allows element position info
to be included in error logging.
Thomas Markwalder 11 years ago
parent
commit
1e69c03467
3 changed files with 80 additions and 11 deletions
  1. 65 11
      src/bin/d2/d2_cfg_mgr.cc
  2. 11 0
      src/bin/d2/d2_cfg_mgr.h
  3. 4 0
      src/bin/d2/tests/d2_cfg_mgr_unittests.cc

+ 65 - 11
src/bin/d2/d2_cfg_mgr.cc

@@ -202,31 +202,85 @@ D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
     // This populate the context scalar stores with all of the parameters.
     DCfgMgrBase::buildParams(params_config);
 
-    // Fetch the parameters from the context to create the D2Params.
+    // Fetch and validate the parameters from the context to create D2Params.
+    // We validate them here rather than just relying on D2Param constructor
+    // so we can spit out config text position info with errors.
+
+    // Fetch and validate io_address.
     D2CfgContextPtr context = getD2CfgContext();
     isc::dhcp::StringStoragePtr strings = context->getStringStorage();
     asiolink::IOAddress ip_address(strings->
                                    getOptionalParam("ip_address",
                                                     D2Params::DFT_IP_ADDRESS));
 
+    if ((ip_address.toText() == "0.0.0.0") || (ip_address.toText() == "::")) {
+        isc_throw(D2CfgError, "IP address cannot be \"" << ip_address << "\" : "
+                   << strings->getPosition("ip_address"));
+    }
+
+    // Fetch and validate port.
     isc::dhcp::Uint32StoragePtr ints = context->getUint32Storage();
     uint32_t port = ints->getOptionalParam("port", D2Params::DFT_PORT);
 
+    if (port == 0) {
+        isc_throw(D2CfgError, "port cannot be 0 : "
+                  << ints->getPosition("port"));
+    }
+
+    // Fetch and validate dns_server_timeout.
     uint32_t dns_server_timeout
         = ints->getOptionalParam("dns_server_timeout",
                                  D2Params::DFT_DNS_SERVER_TIMEOUT);
 
-    dhcp_ddns::NameChangeProtocol ncr_protocol
-        = dhcp_ddns::stringToNcrProtocol(strings->
-                                         getOptionalParam("ncr_protocol",
-                                                          D2Params::
-                                                          DFT_NCR_PROTOCOL));
-    dhcp_ddns::NameChangeFormat ncr_format
-        = dhcp_ddns::stringToNcrFormat(strings->
+    if (dns_server_timeout < 1) {
+        isc_throw(D2CfgError, "DNS server timeout must be larger than 0 : "
+                  << ints->getPosition("dns_server_timeout"));
+    }
+
+    // Fetch and validate ncr_protocol.
+    dhcp_ddns::NameChangeProtocol ncr_protocol;
+    try {
+        ncr_protocol = dhcp_ddns::
+                       stringToNcrProtocol(strings->
+                                           getOptionalParam("ncr_protocol",
+                                                            D2Params::
+                                                            DFT_NCR_PROTOCOL));
+    } catch (const std::exception& ex) {
+        isc_throw(D2CfgError, "ncr_protocol : "
+                  << ex.what() << " : "
+                  << strings->getPosition("ncr_protocol"));
+    }
+
+    if (ncr_protocol != dhcp_ddns::NCR_UDP) {
+        isc_throw(D2CfgError, "ncr_protocol : "
+                  << dhcp_ddns::ncrProtocolToString(ncr_protocol)
+                  << " is not yet supported : "
+                  << strings->getPosition("ncr_protocol"));
+    }
+
+    // Fetch and validate ncr_format.
+    dhcp_ddns::NameChangeFormat ncr_format;
+    try {
+        ncr_format = dhcp_ddns::
+                     stringToNcrFormat(strings->
                                        getOptionalParam("ncr_format",
-                                                          D2Params::
-                                                          DFT_NCR_FORMAT));
-    // Attempt to create the new client config.
+                                                        D2Params::
+                                                        DFT_NCR_FORMAT));
+    } catch (const std::exception& ex) {
+        isc_throw(D2CfgError, "ncr_format : "
+                  << ex.what() << " : "
+                  << strings->getPosition("ncr_format"));
+    }
+
+    if (ncr_format != dhcp_ddns::FMT_JSON) {
+        isc_throw(D2CfgError, "NCR Format:"
+                  << dhcp_ddns::ncrFormatToString(ncr_format)
+                  << " is not yet supported : "
+                  << strings->getPosition("ncr_format"));
+    }
+
+    // Attempt to create the new client config. This ought to fly as
+    // we already validated everything.
     D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
                                     ncr_protocol, ncr_format));
 

+ 11 - 0
src/bin/d2/d2_cfg_mgr.h

@@ -245,7 +245,18 @@ protected:
     /// parameter's id and then invoking its build method passing in the
     /// parameter's configuration value.
     ///
+    /// It then fetches the parameters, validating their values and if
+    /// valid instantiates a D2Params instance.  Invalid values result in
+    /// a throw.
+    ///
     /// @param params_config set of scalar configuration elements to parse
+    ///
+    /// @throw D2CfgError if any of the following are true:
+    /// -# ip_address is 0.0.0.0 or ::
+    /// -# port is 0
+    /// -# dns_server_timeout is < 1
+    /// -# ncr_protocol is invalid, currently only NCR_UDP is supported
+    /// -# ncr_format is invalid, currently only FMT_JSON is supported
     virtual void buildParams(isc::data::ConstElementPtr params_config);
 
     /// @brief Given an element_id returns an instance of the appropriate

+ 4 - 0
src/bin/d2/tests/d2_cfg_mgr_unittests.cc

@@ -472,6 +472,10 @@ TEST_F(D2CfgMgrTest, invalidEntry) {
     config = makeParamsConfigString ("127.0.0.1", 777, 333, "BOGUS", "JSON");
     runConfig(config, SHOULD_FAIL);
 
+    // Unsupported protocol
+    config = makeParamsConfigString ("127.0.0.1", 777, 333, "TCP", "JSON");
+    runConfig(config, SHOULD_FAIL);
+
     // Invalid format
     config = makeParamsConfigString ("127.0.0.1", 777, 333, "UDP", "BOGUS");
     runConfig(config, SHOULD_FAIL);