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);
}
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()) {
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: "
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) {
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;
}
}
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));
}
}
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()) {
/// 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_;
/// @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".
/// 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.