+2250. [bug] tmark
+ Corrected an issue with overlapping enum values
+ for option definition data type. This was causing
+ option definitions of type "record", created via
+ config backend commands, to not load properly when
+ fetched from the back end.
+ (Gitlab #3484, #3476)
+
2249. [bug] marcin
Corrected a bug in storing and fetching the encapsulated DHCP
options from the configuration backend. These options were
sometimes not returned when they were specified at the subnet,
shared network or client class level.
(Gitlab #3485)
-
2248. [bug] razvan
Fixed a file descriptor leak in the High Availability hook
library.
optionDefs4WithServerTagsTest();
}
+TEST_F(MySqlConfigBackendDHCPv4Test, invalidOptionDefDataType4Test) {
+ invalidOptionDefDataType4Test();
+}
+
+TEST_F(MySqlConfigBackendDHCPv4Test, allOptionDefDataTypes4Test) {
+ allOptionDefDataTypes4Test();
+}
+
TEST_F(MySqlConfigBackendDHCPv4Test, getAllOptionDefs4Test) {
getAllOptionDefs4Test();
}
optionDefs6WithServerTagsTest();
}
+TEST_F(MySqlConfigBackendDHCPv6Test, invalidOptionDefDataType6Test) {
+ invalidOptionDefDataType6Test();
+}
+
+TEST_F(MySqlConfigBackendDHCPv6Test, allOptionDefDataTypes6Test) {
+ allOptionDefDataTypes6Test();
+}
+
TEST_F(MySqlConfigBackendDHCPv6Test, getAllOptionDefs6Test) {
getAllOptionDefs6Test();
}
optionDefs4WithServerTagsTest();
}
+TEST_F(PgSqlConfigBackendDHCPv4Test, invalidOptionDefDataType4Test) {
+ invalidOptionDefDataType4Test();
+}
+
+TEST_F(PgSqlConfigBackendDHCPv4Test, allOptionDefDataTypes4Test) {
+ allOptionDefDataTypes4Test();
+}
+
TEST_F(PgSqlConfigBackendDHCPv4Test, getAllOptionDefs4Test) {
getAllOptionDefs4Test();
}
optionDefs6WithServerTagsTest();
}
+TEST_F(PgSqlConfigBackendDHCPv6Test, invalidOptionDefDataType6Test) {
+ invalidOptionDefDataType6Test();
+}
+
+TEST_F(PgSqlConfigBackendDHCPv6Test, allOptionDefDataTypes4Test) {
+ allOptionDefDataTypes6Test();
+}
+
TEST_F(PgSqlConfigBackendDHCPv6Test, getAllOptionDefs6Test) {
getAllOptionDefs6Test();
}
OPT_FQDN_TYPE,
// Type to be used only internally. Allows convenient notation of the option config.
OPT_INTERNAL_TYPE,
- OPT_RECORD_TYPE,
- OPT_UNKNOWN_TYPE
+ OPT_RECORD_TYPE = 254, // Do not alter this value.
+ OPT_UNKNOWN_TYPE = 255 // Do not alter this value.
};
/// @brief Parameters being used to make up an option definition.
option_cast->toText());
}
+// Verify converstion of OptionDefintion type strings to type enums.
+TEST(OptionDataTypeUtil, typeToString) {
+ EXPECT_EQ(OPT_EMPTY_TYPE, OptionDataTypeUtil::getDataType("empty"));
+ EXPECT_EQ(OPT_BINARY_TYPE, OptionDataTypeUtil::getDataType("binary"));
+ EXPECT_EQ(OPT_BOOLEAN_TYPE, OptionDataTypeUtil::getDataType("boolean"));
+ EXPECT_EQ(OPT_INT8_TYPE, OptionDataTypeUtil::getDataType("int8"));
+ EXPECT_EQ(OPT_INT16_TYPE, OptionDataTypeUtil::getDataType("int16"));
+ EXPECT_EQ(OPT_INT32_TYPE, OptionDataTypeUtil::getDataType("int32"));
+ EXPECT_EQ(OPT_UINT8_TYPE, OptionDataTypeUtil::getDataType("uint8"));
+ EXPECT_EQ(OPT_UINT16_TYPE, OptionDataTypeUtil::getDataType("uint16"));
+ EXPECT_EQ(OPT_UINT32_TYPE, OptionDataTypeUtil::getDataType("uint32"));
+ EXPECT_EQ(OPT_IPV4_ADDRESS_TYPE, OptionDataTypeUtil::getDataType("ipv4-address"));
+ EXPECT_EQ(OPT_IPV6_ADDRESS_TYPE, OptionDataTypeUtil::getDataType("ipv6-address"));
+ EXPECT_EQ(OPT_IPV6_PREFIX_TYPE, OptionDataTypeUtil::getDataType("ipv6-prefix"));
+ EXPECT_EQ(OPT_PSID_TYPE, OptionDataTypeUtil::getDataType("psid"));
+ EXPECT_EQ(OPT_STRING_TYPE, OptionDataTypeUtil::getDataType("string"));
+ EXPECT_EQ(OPT_TUPLE_TYPE, OptionDataTypeUtil::getDataType("tuple"));
+ EXPECT_EQ(OPT_FQDN_TYPE, OptionDataTypeUtil::getDataType("fqdn"));
+ // EXPECT_EQ(OPT_INTERNAL_TYPE, OptionDataTypeUtil::getDataType("internal"));
+ EXPECT_EQ(OPT_RECORD_TYPE, OptionDataTypeUtil::getDataType("record"));
+ EXPECT_EQ(OPT_UNKNOWN_TYPE, OptionDataTypeUtil::getDataType("bogus"));
+}
+
+// Verify converstion of OptionDefintion type enums to type strings.
+TEST(OptionDataTypeUtil, stringToType) {
+ EXPECT_EQ("empty", OptionDataTypeUtil::getDataTypeName(OPT_EMPTY_TYPE));
+ EXPECT_EQ("binary", OptionDataTypeUtil::getDataTypeName( OPT_BINARY_TYPE));
+ EXPECT_EQ("boolean", OptionDataTypeUtil::getDataTypeName(OPT_BOOLEAN_TYPE));
+ EXPECT_EQ("int8", OptionDataTypeUtil::getDataTypeName(OPT_INT8_TYPE));
+ EXPECT_EQ("int16", OptionDataTypeUtil::getDataTypeName(OPT_INT16_TYPE));
+ EXPECT_EQ("int32", OptionDataTypeUtil::getDataTypeName(OPT_INT32_TYPE));
+ EXPECT_EQ("uint8", OptionDataTypeUtil::getDataTypeName(OPT_UINT8_TYPE));
+ EXPECT_EQ("uint16", OptionDataTypeUtil::getDataTypeName(OPT_UINT16_TYPE));
+ EXPECT_EQ("uint32", OptionDataTypeUtil::getDataTypeName(OPT_UINT32_TYPE));
+ EXPECT_EQ("ipv4-address", OptionDataTypeUtil::getDataTypeName(OPT_IPV4_ADDRESS_TYPE));
+ EXPECT_EQ("ipv6-address", OptionDataTypeUtil::getDataTypeName(OPT_IPV6_ADDRESS_TYPE));
+ EXPECT_EQ("ipv6-prefix", OptionDataTypeUtil::getDataTypeName(OPT_IPV6_PREFIX_TYPE));
+ EXPECT_EQ("psid", OptionDataTypeUtil::getDataTypeName(OPT_PSID_TYPE));
+ EXPECT_EQ("string", OptionDataTypeUtil::getDataTypeName(OPT_STRING_TYPE));
+ EXPECT_EQ("tuple", OptionDataTypeUtil::getDataTypeName(OPT_TUPLE_TYPE));
+ EXPECT_EQ("fqdn", OptionDataTypeUtil::getDataTypeName(OPT_FQDN_TYPE));
+ // EXPECT_EQ("internal", OptionDataTypeUtil::getDataTypeName(OPT_INTERNAL_TYPE));
+ EXPECT_EQ("record", OptionDataTypeUtil::getDataTypeName(OPT_RECORD_TYPE));
+ EXPECT_EQ("unknown", OptionDataTypeUtil::getDataTypeName(OPT_UNKNOWN_TYPE));
+}
+
} // anonymous namespace
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/client_class_def.h>
#include <dhcpsrv/config_backend_dhcp4_mgr.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/testutils/generic_cb_dhcp4_unittest.h>
test_option_defs_.push_back(option_def);
option_def.reset(new OptionDefinition("foobar", 234, DHCP4_OPTION_SPACE,
- "uint64", true));
+ "uint16", true));
test_option_defs_.push_back(option_def);
}
distance--;
}
}
+
+void
+GenericConfigBackendDHCPv4Test::invalidOptionDefDataType4Test() {
+ OptionDefinitionPtr test_def;
+ ASSERT_NO_THROW_LOG(test_def.reset(new OptionDefinition("foobar", 234, DHCP4_OPTION_SPACE,
+ "unknown", true)));
+ ASSERT_TRUE(test_def);
+ ASSERT_THROW(cbptr_->createUpdateOptionDef4(ServerSelector::ALL(), test_def),
+ DbOperationError);
+}
+
+void
+GenericConfigBackendDHCPv4Test::allOptionDefDataTypes4Test() {
+
+ OptionDefListParser parser(AF_INET);
+ std::string defs_str = R"([
+ {
+ "name": "my-empty", "code": 221, "type": "empty", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-binary", "code": 222, "type": "binary", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-boolean", "code": 223, "type": "boolean", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-int8", "code": 224, "type": "int8", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-int16", "code": 225, "type": "int16", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-int32", "code": 226, "type": "int32", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-uint8", "code": 227, "type": "uint8", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-uint16", "code": 228, "type": "uint16", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-uint32", "code": 229, "type": "uint32", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-ipv4-address", "code": 230, "type": "ipv4-address", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-ipv6-address", "code": 231, "type": "ipv6-address", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-ipv6-prefix", "code": 232, "type": "ipv6-prefix", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-psid", "code": 233, "type": "psid", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-string", "code": 234, "type": "string", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-tuple", "code": 235, "type": "tuple", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-fqdn", "code": 236, "type": "fqdn", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-internal", "code": 237, "type": "internal", "array": false,
+ "record-types": "", "space": "dhcp4", "encapsulate": ""
+ },
+ {
+ "name": "my-record", "code": 238, "type": "record", "array": false,
+ "record-types": "uint8, uint8", "space": "dhcp4", "encapsulate": ""
+ }
+ ])";
+
+ ConstElementPtr defs_elem;
+ ASSERT_NO_THROW_LOG(defs_elem = Element::fromJSON(defs_str));
+
+ CfgOptionDefPtr storage(new CfgOptionDef());
+ ASSERT_NO_THROW_LOG(parser.parse(storage, defs_elem));
+
+ auto test_defs = storage->getAll("dhcp4");
+ ASSERT_EQ(test_defs->size(), 18);
+
+ // Insert each option definition into the database.
+ for (auto const& test_def : *test_defs) {
+ ASSERT_NO_THROW_LOG(cbptr_->createUpdateOptionDef4(ServerSelector::ALL(), test_def));
+ auto found_def = cbptr_->getOptionDef4(ServerSelector::ALL(),
+ test_def->getCode(), "dhcp4");
+
+ ASSERT_TRUE(found_def) << "no option found for " << test_def->getName();
+ ASSERT_EQ(*found_def, *test_def);
+ std::cout << "option ok for " << found_def->getName() << std::endl;
+ }
+}
/// all servers.
void optionDefs4WithServerTagsTest();
+ /// @brief This test verifies that the back end prevents storage
+ /// of definitions with invalid data types
+ void invalidOptionDefDataType4Test();
+
+ /// @brief This test verifies that it is possible to create options of each
+ /// valid data type.
+ void allOptionDefDataTypes4Test();
+
/// @brief Test that all option definitions can be fetched.
void getAllOptionDefs4Test();
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/client_class_def.h>
#include <dhcpsrv/config_backend_dhcp6_mgr.h>
+#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <dhcpsrv/pool.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/testutils/generic_cb_dhcp6_unittest.h>
test_option_defs_.push_back(option_def);
option_def.reset(new OptionDefinition("bar", 1234, DHCP6_OPTION_SPACE,
- "uint64", true));
+ "uint16", true));
test_option_defs_.push_back(option_def);
}
distance--;
}
}
+
+void
+GenericConfigBackendDHCPv6Test::invalidOptionDefDataType6Test() {
+ OptionDefinitionPtr test_def;
+ ASSERT_NO_THROW_LOG(test_def.reset(new OptionDefinition("foobar", 234, DHCP6_OPTION_SPACE,
+ "unknown", true)));
+ ASSERT_TRUE(test_def);
+ ASSERT_THROW(cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), test_def),
+ DbOperationError);
+}
+
+void
+GenericConfigBackendDHCPv6Test::allOptionDefDataTypes6Test() {
+
+ OptionDefListParser parser(AF_INET);
+ std::string defs_str = R"([
+ {
+ "name": "my-empty", "code": 221, "type": "empty", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-binary", "code": 222, "type": "binary", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-boolean", "code": 223, "type": "boolean", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-int8", "code": 224, "type": "int8", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-int16", "code": 225, "type": "int16", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-int32", "code": 226, "type": "int32", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-uint8", "code": 227, "type": "uint8", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-uint16", "code": 228, "type": "uint16", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-uint32", "code": 229, "type": "uint32", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-ipv4-address", "code": 230, "type": "ipv4-address", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-ipv6-address", "code": 231, "type": "ipv6-address", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-ipv6-prefix", "code": 232, "type": "ipv6-prefix", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-psid", "code": 233, "type": "psid", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-string", "code": 234, "type": "string", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-tuple", "code": 235, "type": "tuple", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-fqdn", "code": 236, "type": "fqdn", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-internal", "code": 237, "type": "internal", "array": false,
+ "record-types": "", "space": "dhcp6", "encapsulate": ""
+ },
+ {
+ "name": "my-record", "code": 238, "type": "record", "array": false,
+ "record-types": "uint8, uint8", "space": "dhcp6", "encapsulate": ""
+ }
+ ])";
+
+ ConstElementPtr defs_elem;
+ ASSERT_NO_THROW_LOG(defs_elem = Element::fromJSON(defs_str));
+
+ CfgOptionDefPtr storage(new CfgOptionDef());
+ ASSERT_NO_THROW_LOG(parser.parse(storage, defs_elem));
+
+ auto test_defs = storage->getAll("dhcp6");
+ ASSERT_EQ(test_defs->size(), 18);
+
+ // Insert each option definition into the database.
+ for (auto const& test_def : *test_defs) {
+ ASSERT_NO_THROW_LOG(cbptr_->createUpdateOptionDef6(ServerSelector::ALL(), test_def));
+ auto found_def = cbptr_->getOptionDef6(ServerSelector::ALL(),
+ test_def->getCode(), "dhcp6");
+
+ ASSERT_TRUE(found_def) << "no option found for " << test_def->getName();
+ ASSERT_EQ(*found_def, *test_def);
+ std::cout << "option ok for " << found_def->getName() << std::endl;
+ }
+}
-// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2022-2024 Internet Systems Consortium, Inc. ("ISC")
//
// 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
/// all servers.
void optionDefs6WithServerTagsTest();
+ /// @brief This test verifies that the back end prevents storage
+ /// of definitions with invalid data types
+ void invalidOptionDefDataType6Test();
+
+ /// @brief This test verifies that it is possible to create options of each
+ /// valid data type.
+ void allOptionDefDataTypes6Test();
+
/// @brief Test that all option definitions can be fetched.
void getAllOptionDefs6Test();