Browse Source

[3705] ""relay-supplied-options" parameter added.

Tomek Mrugalski 10 years ago
parent
commit
4495b7a713
2 changed files with 153 additions and 0 deletions
  1. 66 0
      src/bin/dhcp6/json_config_parser.cc
  2. 87 0
      src/bin/dhcp6/tests/config_parser_unittest.cc

+ 66 - 0
src/bin/dhcp6/json_config_parser.cc

@@ -575,6 +575,70 @@ public:
     ParserCollection subnets_;
 };
 
+/// @brief parser for list of RSOO options
+///
+/// This parser handles Dhcp6/relay-supplied-options entry.
+/// It contains a list of option codes.
+class RSOOListConfigParser : public DhcpConfigParser {
+public:
+
+    /// @brief constructor
+    ///
+    /// As this is a dedicated parser, it must be used to parse
+    /// "relay-supplied-options" parameter only. All other types will throw exception.
+    ///
+    /// @param param_name name of the configuration parameter being parsed
+    /// @throw BadValue if supplied parameter name is not "relay-supplied-options"
+    RSOOListConfigParser(const std::string& param_name) {
+        if (param_name != "relay-supplied-options") {
+            isc_throw(BadValue, "Internal error. RSOO configuration "
+                      "parser called for the wrong parameter: " << param_name);
+        }
+    }
+
+    /// @brief parses parameters value
+    ///
+    /// Parses configuration entry (list of sources) and adds each element
+    /// to the RSOO list.
+    ///
+    /// @param value pointer to the content of parsed values
+    virtual void build(isc::data::ConstElementPtr value) {
+
+        // By default, there's only one RSOO option defined: 65
+        // http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml
+        CfgMgr::instance().getStagingCfg()->getCfgOption()->clearRSOO();
+        CfgMgr::instance().getStagingCfg()->getCfgOption()->addRSOO(D6O_ERP_LOCAL_DOMAIN_NAME);
+
+        BOOST_FOREACH(ConstElementPtr source_elem, value->listValue()) {
+
+            std::string option_str = source_elem->stringValue();
+            // This option can be either code (integer) or name. Let's try code first
+            uint16_t code = 0;
+            try {
+                code = boost::lexical_cast<uint16_t>(option_str);
+            } catch (const boost::bad_lexical_cast &) {
+                // Oh well, it's not a number
+            }
+
+            if (!code) {
+                OptionDefinitionPtr def = LibDHCP::getOptionDef(Option::V6, option_str);
+                if (def) {
+                    code = def->getCode();
+                } else {
+                    isc_throw(BadValue, "Unable to convert '" << option_str
+                              << "' to option code while parsing allowed"
+                              << "relay-supplied-options");
+                }
+            }
+            CfgMgr::instance().getStagingCfg()->getCfgOption()->addRSOO(code);
+        }
+    }
+
+    /// @brief Does nothing.
+    virtual void commit() {}
+};
+
+
 } // anonymous namespace
 
 namespace isc {
@@ -618,6 +682,8 @@ namespace dhcp {
     } else if (config_id.compare("mac-sources") == 0) {
         parser = new MACSourcesListConfigParser(config_id,
                                                 globalContext());
+    } else if (config_id.compare("relay-supplied-options") == 0) {
+        parser = new RSOOListConfigParser(config_id);
     } else {
         isc_throw(DhcpConfigError,
                 "unsupported global configuration parameter: "

+ 87 - 0
src/bin/dhcp6/tests/config_parser_unittest.cc

@@ -3779,4 +3779,91 @@ TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
     EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode());
 }
 
+/// The goal of this test is to verify that configuration can include
+/// Relay Supplied options (specified as numbers).
+TEST_F(Dhcp6ParserTest, rsooNumbers) {
+
+    ConstElementPtr status;
+
+    EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
+        Element::fromJSON("{ " + genIfaceConfig() + ","
+                          "\"relay-supplied-options\": [ \"10\", \"20\", \"30\" ],"
+                          "\"preferred-lifetime\": 3000,"
+                          "\"rebind-timer\": 2000, "
+                          "\"renew-timer\": 1000, "
+                          "\"subnet6\": [  ], "
+                          "\"valid-lifetime\": 4000 }")));
+
+    // returned value should be 0 (success)
+    checkResult(status, 0);
+
+    // The following codes should be enabled now
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(10));
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(20));
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(30));
+
+    // This option is on the IANA list, so it should be allowed all the time
+    // (http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml)
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                ->isRSOOEnabled(D6O_ERP_LOCAL_DOMAIN_NAME));
+
+    // Those options are not enabled
+    EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(25));
+    EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()->isRSOOEnabled(1));
+}
+
+/// The goal of this test is to verify that configuration can include
+/// Relay Supplied options (specified as names).
+TEST_F(Dhcp6ParserTest, rsooNames) {
+
+    ConstElementPtr status;
+
+    EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
+        Element::fromJSON("{ " + genIfaceConfig() + ","
+                          "\"relay-supplied-options\": [ \"dns-servers\", \"remote-id\" ],"
+                          "\"preferred-lifetime\": 3000,"
+                          "\"rebind-timer\": 2000, "
+                          "\"renew-timer\": 1000, "
+                          "\"subnet6\": [  ], "
+                          "\"valid-lifetime\": 4000 }")));
+
+    // returned value should be 0 (success)
+    checkResult(status, 0);
+
+    for (uint16_t code = 0; code < D6O_NAME_SERVERS; ++code) {
+        EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                     ->isRSOOEnabled(code)) << " for option code " << code;
+    }
+
+    // The following codes should be enabled now
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                ->isRSOOEnabled(D6O_NAME_SERVERS));
+
+    for (uint16_t code = D6O_NAME_SERVERS + 1; code < D6O_REMOTE_ID; ++code) {
+        EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                     ->isRSOOEnabled(code)) << " for option code " << code;
+    }
+
+    // Check remote-id. It should be enabled.
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                ->isRSOOEnabled(D6O_REMOTE_ID));
+    for (uint16_t code = D6O_REMOTE_ID + 1; code < D6O_ERP_LOCAL_DOMAIN_NAME; ++code) {
+        EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                     ->isRSOOEnabled(code)) << " for option code " << code;
+    }
+
+    // This option is on the IANA list, so it should be allowed all the time
+    // (http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml)
+    EXPECT_TRUE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                ->isRSOOEnabled(D6O_ERP_LOCAL_DOMAIN_NAME));
+
+    for (uint16_t code = D6O_ERP_LOCAL_DOMAIN_NAME + 1; code < 300; ++code) {
+        EXPECT_FALSE(CfgMgr::instance().getStagingCfg()->getCfgOption()
+                     ->isRSOOEnabled(code)) << " for option code " << code;
+    }
+
+
+}
+
+
 };