Browse Source

[3747] Update configuration parsers to support ignore-client-id.

Marcin Siodelski 10 years ago
parent
commit
1e2bfcdc46

+ 26 - 1
src/bin/dhcp4/json_config_parser.cc

@@ -194,6 +194,8 @@ protected:
             parser = new RelayInfoParser(config_id, relay_info_, Option::V4);
         } else if (config_id.compare("option-data") == 0) {
             parser = new OptionDataListParser(config_id, options_, AF_INET);
+        } else if (config_id.compare("ignore-client-id") == 0) {
+            parser = new BooleanParser(config_id, boolean_values_);
         } else {
             isc_throw(NotImplemented, "unsupported parameter: " << config_id);
         }
@@ -250,7 +252,28 @@ protected:
         Subnet4Ptr subnet4(new Subnet4(addr, len, t1, t2, valid, subnet_id));
         subnet_ = subnet4;
 
-        // Try global value first
+        // ignore-client-id
+        isc::util::OptionalValue<bool> ignore_client_id;
+        try {
+            ignore_client_id = boolean_values_->getParam("ignore-client-id");
+
+        } catch (...) {
+            // Ignore because this parameter is optional and it may be specified
+            // in the global scope.
+        }
+
+        // If the ignore-client-id wasn't specified as a subnet specific parameter
+        // check if there is global value specified.
+        if (!ignore_client_id.isSpecified()) {
+            // If not specified, use false.
+            ignore_client_id.specify(globalContext()->boolean_values_->
+                                     getOptionalParam("ignore-client-id", false));
+        }
+
+        // Set the ignore-client-id value for the subnet.
+        subnet4->setIgnoreClientId(ignore_client_id.get());
+
+        // next-server
         try {
             string next_server = globalContext()->string_values_->getParam("next-server");
             if (!next_server.empty()) {
@@ -374,6 +397,8 @@ namespace dhcp {
         parser = new BooleanParser(config_id, globalContext()->boolean_values_);
     } else if (config_id.compare("dhcp-ddns") == 0) {
         parser = new D2ClientConfigParser(config_id);
+    } else if (config_id.compare("ignore-client-id") == 0) {
+        parser = new BooleanParser(config_id, globalContext()->boolean_values_);
     } else {
         isc_throw(DhcpConfigError,
                 "unsupported global configuration parameter: "

+ 71 - 0
src/bin/dhcp4/tests/config_parser_unittest.cc

@@ -1102,6 +1102,77 @@ TEST_F(Dhcp4ParserTest, echoClientId) {
     CfgMgr::instance().echoClientId(true);
 }
 
+// This test checks that the global ignore-client-id parameter is optional
+// and that values under the subnet are used.
+TEST_F(Dhcp4ParserTest, ignoreClientIdNoGlobal) {
+    ConstElementPtr status;
+
+    std::string config = "{ " + genIfaceConfig() + "," +
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet4\": [ "
+        "{"
+        "    \"ignore-client-id\": true,"
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\""
+        "},"
+        "{"
+        "    \"ignore-client-id\": false,"
+        "    \"pools\": [ { \"pool\": \"192.0.3.1 - 192.0.3.100\" } ],"
+        "    \"subnet\": \"192.0.3.0/24\""
+        "} ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ElementPtr json = Element::fromJSON(config);
+    ASSERT_NO_THROW(status = configureDhcp4Server(*srv_, json));
+    checkResult(status, 0);
+
+    CfgSubnets4Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+    Subnet4Ptr subnet1 = cfg->selectSubnet(IOAddress("192.0.2.1"));
+    ASSERT_TRUE(subnet1);
+    EXPECT_TRUE(subnet1->getIgnoreClientId());
+
+    Subnet4Ptr subnet2 = cfg->selectSubnet(IOAddress("192.0.3.1"));
+    ASSERT_TRUE(subnet2);
+    EXPECT_FALSE(subnet2->getIgnoreClientId());
+}
+
+// This test checks that the global ignore-client-id parameter is used
+// when there is no such parameter under subnet and that the parameter
+// specified for a subnet overrides the global setting.
+TEST_F(Dhcp4ParserTest, ignoreClientIdGlobal) {
+    ConstElementPtr status;
+
+    std::string config = "{ " + genIfaceConfig() + "," +
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"ignore-client-id\": true,"
+        "\"subnet4\": [ "
+        "{"
+        "    \"ignore-client-id\": false,"
+        "    \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+        "    \"subnet\": \"192.0.2.0/24\""
+        "},"
+        "{"
+        "    \"pools\": [ { \"pool\": \"192.0.3.1 - 192.0.3.100\" } ],"
+        "    \"subnet\": \"192.0.3.0/24\""
+        "} ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ElementPtr json = Element::fromJSON(config);
+    ASSERT_NO_THROW(status = configureDhcp4Server(*srv_, json));
+    checkResult(status, 0);
+
+    CfgSubnets4Ptr cfg = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
+    Subnet4Ptr subnet1 = cfg->selectSubnet(IOAddress("192.0.2.1"));
+    ASSERT_TRUE(subnet1);
+    EXPECT_FALSE(subnet1->getIgnoreClientId());
+
+    Subnet4Ptr subnet2 = cfg->selectSubnet(IOAddress("192.0.3.1"));
+    ASSERT_TRUE(subnet2);
+    EXPECT_TRUE(subnet2->getIgnoreClientId());
+}
+
 // This test checks if it is possible to override global values
 // on a per subnet basis.
 TEST_F(Dhcp4ParserTest, subnetLocal) {

+ 2 - 2
src/lib/dhcp/iface_mgr.cc

@@ -238,7 +238,7 @@ Iface::setActive(const IOAddress& address, const bool active) {
     for (AddressCollection::iterator addr_it = addrs_.begin();
          addr_it != addrs_.end(); ++addr_it) {
         if (address == addr_it->get()) {
-            addr_it->specify(active);
+            addr_it->specify(OptionalValueState(active));
             return;
         }
     }
@@ -250,7 +250,7 @@ void
 Iface::setActive(const bool active) {
     for (AddressCollection::iterator addr_it = addrs_.begin();
          addr_it != addrs_.end(); ++addr_it) {
-        addr_it->specify(active);
+        addr_it->specify(OptionalValueState(active));
     }
 }
 

+ 3 - 1
src/lib/dhcpsrv/parsers/dhcp_parsers.cc

@@ -1030,7 +1030,9 @@ PoolParser::commit() {
 SubnetConfigParser::SubnetConfigParser(const std::string&,
                                        ParserContextPtr global_context,
                                        const isc::asiolink::IOAddress& default_addr)
-    : uint32_values_(new Uint32Storage()), string_values_(new StringStorage()),
+    : uint32_values_(new Uint32Storage()),
+      string_values_(new StringStorage()),
+      boolean_values_(new BooleanStorage()),
       pools_(new PoolStorage()), global_context_(global_context),
       relay_info_(new isc::dhcp::Subnet::RelayInfo(default_addr)),
       options_(new CfgOption()) {

+ 3 - 0
src/lib/dhcpsrv/parsers/dhcp_parsers.h

@@ -1063,6 +1063,9 @@ protected:
     /// Storage for subnet-specific string values.
     StringStoragePtr string_values_;
 
+    /// Storage for subnet-specific boolean values.
+    BooleanStoragePtr boolean_values_;
+
     /// Storage for pools belonging to this subnet.
     PoolStoragePtr pools_;
 

+ 3 - 7
src/lib/util/optional_value.h

@@ -100,11 +100,7 @@ public:
     /// @param value New actual value.
     void specify(const T& value) {
         set(value);
-        specify(true);
-    }
-
-    void specify(const OptionalValueState& state) {
-        specified_ = state.specified_;
+        specify(OptionalValueState(true));
     }
 
     /// @brief Sets the value to "specified" or "unspecified".
@@ -112,8 +108,8 @@ public:
     /// It does not alter the actual value. It only marks it "specified" or
     /// "unspecified".
     /// @param specified boolean that determined if a value is specified or not
-    void specify(const bool specified) {
-        specified_ = specified;
+    void specify(const OptionalValueState& state) {
+        specified_ = state.specified_;
     }
 
     /// @brief Checks if the value is specified or unspecified.