]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2314] Checkpoint: added space
authorFrancis Dupont <fdupont@isc.org>
Thu, 17 Mar 2022 17:58:35 +0000 (18:58 +0100)
committerRazvan Becheriu <razvan@isc.org>
Wed, 23 Mar 2022 07:50:03 +0000 (09:50 +0200)
doc/sphinx/arm/hooks.rst
src/hooks/dhcp/flex_option/flex_option.cc
src/hooks/dhcp/flex_option/tests/flex_option_unittests.cc

index 5f4ec8cadf4c832634bfb8dcc0a847c6e8da812b..ff966db939c075043ab2c9e469239c219173beda 100644 (file)
@@ -1878,7 +1878,10 @@ a client class name, when not empty the entry is skipped if the query does
 not belong to the class.
 
 Since Kea 2.1.4, it is allowed to have multiple entries for the same option,
-but each entry must have exactly one action.
+but each entry must have exactly one action. If the option is not defined
+in the ``dhcp4`` for DHCPv4 or ``dhcp6`` for DHCPv6 you can specify the
+space where to find the option definition using its name with the new
+``space`` parameter.
 
 .. _host-cmds:
 
index accad60291bf800df1aa8a86d629d30f945638e4..87daff7acd4896c0e4584e90c818e7c1ec5b1ba8 100644 (file)
@@ -73,6 +73,7 @@ namespace flex_option {
 const SimpleKeywords FlexOptionImpl::OPTION_PARAMETERS = {
   { "code",             Element::integer },
   { "name",             Element::string },
+  { "space",            Element::string },
   { "csv-format",       Element::boolean },
   { "add",              Element::string },
   { "supersede",        Element::string },
@@ -137,6 +138,7 @@ FlexOptionImpl::parseOptionConfig(ConstElementPtr option) {
     }
     ConstElementPtr code_elem = option->get("code");
     ConstElementPtr name_elem = option->get("name");
+    ConstElementPtr space_elem = option->get("space");
     ConstElementPtr csv_format_elem = option->get("csv-format");
     ConstElementPtr class_elem = option->get("client-class");
     OptionDefinitionPtr def;
@@ -153,6 +155,12 @@ FlexOptionImpl::parseOptionConfig(ConstElementPtr option) {
         space = DHCP6_OPTION_SPACE;
         universe = Option::V6;
     }
+    if (space_elem) {
+        space = space_elem->stringValue();
+        if (!OptionSpace::validateName(space)) {
+            isc_throw(BadValue, "'" << space << "' is not a valid space name");
+        }
+    }
     uint16_t code;
     if (code_elem) {
         int64_t value = code_elem->intValue();
@@ -166,7 +174,7 @@ FlexOptionImpl::parseOptionConfig(ConstElementPtr option) {
             isc_throw(OutOfRange, "invalid 'code' value " << value
                       << " not in [0.." << max_code << "]");
         }
-        if (family == AF_INET) {
+        if (space == DHCP4_OPTION_SPACE) {
             if (value == DHO_PAD) {
                 isc_throw(BadValue,
                           "invalid 'code' value 0: reserved for PAD");
@@ -174,7 +182,7 @@ FlexOptionImpl::parseOptionConfig(ConstElementPtr option) {
                 isc_throw(BadValue,
                           "invalid 'code' value 255: reserved for END");
             }
-        } else {
+        } else if (space == DHCP6_OPTION_SPACE) {
             if (value == 0) {
                 isc_throw(BadValue, "invalid 'code' value 0: reserved");
             }
index 35504ce756320eb2f24070049a2608dabf6b0c65..8dc841520b36e9af578005a98628406e0536e8f1 100644 (file)
@@ -228,6 +228,36 @@ TEST_F(FlexOptionTest, optionConfigBadCode6) {
     EXPECT_TRUE(impl_->getErrMsg().empty());
 }
 
+// Verify that the space must be a string.
+TEST_F(FlexOptionTest, optionConfigBadSpace) {
+    ElementPtr options = Element::createList();
+    ElementPtr option = Element::createMap();
+    options->add(option);
+    ElementPtr add = Element::create(string("'ab'"));
+    option->set("add", add);
+    ElementPtr code = Element::create(222);
+    option->set("code", code);
+    ElementPtr space = Element::create(true);
+    option->set("space", space);
+    EXPECT_THROW(impl_->testConfigure(options), BadValue);
+    EXPECT_EQ("'space' must be a string: true", impl_->getErrMsg());
+}
+
+// Verify that the space must be valid.
+TEST_F(FlexOptionTest, optionConfigInvalidSpace) {
+    ElementPtr options = Element::createList();
+    ElementPtr option = Element::createMap();
+    options->add(option);
+    ElementPtr add = Element::create(string("'ab'"));
+    option->set("add", add);
+    ElementPtr code = Element::create(222);
+    option->set("code", code);
+    ElementPtr space = Element::create(string("-bad-"));
+    option->set("space", space);
+    EXPECT_THROW(impl_->testConfigure(options), BadValue);
+    EXPECT_EQ("'-bad-' is not a valid space name", impl_->getErrMsg());
+}
+
 // Verify that the name must be a string.
 TEST_F(FlexOptionTest, optionConfigBadName) {
     ElementPtr options = Element::createList();
@@ -267,6 +297,22 @@ TEST_F(FlexOptionTest, optionConfigUnknownName) {
     EXPECT_EQ("no known 'foobar' option in 'dhcp4' space", impl_->getErrMsg());
 }
 
+// Verify that the space must be a known space.
+TEST_F(FlexOptionTest, optionConfigUnknownSpace) {
+    ElementPtr options = Element::createList();
+    ElementPtr option = Element::createMap();
+    options->add(option);
+    ElementPtr add = Element::create(string("'ab'"));
+    option->set("add", add);
+    ElementPtr name = Element::create(string("host-name"));
+    option->set("name", name);
+    ElementPtr space = Element::create(string("foobar"));
+    option->set("space", space);
+    EXPECT_THROW(impl_->testConfigure(options), BadValue);
+    EXPECT_EQ("no known 'host-name' option in 'foobar' space",
+              impl_->getErrMsg());
+}
+
 // Verify that the definition is not required when csv-format is not specified.
 TEST_F(FlexOptionTest, optionConfigUnknownCodeNoCSVFormat) {
     ElementPtr options = Element::createList();
@@ -362,6 +408,32 @@ TEST_F(FlexOptionTest, optionConfigDefinedName) {
     EXPECT_EQ(1, opt_lst.size());
 }
 
+// Verify that the name can be an user defined option in a custom space.
+TEST_F(FlexOptionTest, optionConfigDefinedSpace) {
+    OptionDefSpaceContainer defs;
+    OptionDefinitionPtr def(new OptionDefinition("my-option", 222,
+                                                 "my-space", "string"));
+    defs.addItem(def);
+    EXPECT_NO_THROW(LibDHCP::setRuntimeOptionDefs(defs));
+
+    ElementPtr options = Element::createList();
+    ElementPtr option = Element::createMap();
+    options->add(option);
+    ElementPtr add = Element::create(string("'ab'"));
+    option->set("add", add);
+    ElementPtr name = Element::create(string("my-option"));
+    option->set("name", name);
+    ElementPtr space = Element::create(string("my-space"));
+    option->set("space", space);
+    EXPECT_NO_THROW(impl_->testConfigure(options));
+    EXPECT_TRUE(impl_->getErrMsg().empty());
+
+    auto map = impl_->getOptionConfigMap();
+    EXPECT_EQ(1, map.count(222));
+    auto opt_lst = map[222];
+    EXPECT_EQ(1, opt_lst.size());
+}
+
 // Last resort is only option 43...
 
 // Verify that the name must match the code.