Browse Source

[3274] RelayInfo parser implemented.

Tomek Mrugalski 11 years ago
parent
commit
353cb22576

+ 47 - 0
src/lib/dhcpsrv/dhcp_parsers.cc

@@ -812,6 +812,53 @@ OptionDefListParser::commit() {
 }
 
 //****************************** PoolParser ********************************
+RelayInfoParser::RelayInfoParser(const std::string&,
+                                 const isc::dhcp::Subnet::RelayInfoPtr& relay_info,
+                                 const asiolink::IOAddress& default_addr)
+    :storage_(relay_info), local_(default_addr),
+     string_values_(new StringStorage()) {
+    if (!relay_info) {
+        isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
+                  << "relay-info storage may not be NULL");
+    }
+
+};
+
+void
+RelayInfoParser::build(ConstElementPtr relay_info) {
+
+    BOOST_FOREACH(ConfigPair param, relay_info->mapValue()) {
+        ParserPtr parser(createConfigParser(param.first));
+        parser->build(param.second);
+        parser->commit();
+    }
+
+    // Get the IP address
+    asiolink::IOAddress ip(string_values_->getParam("ip-address"));
+
+    local_.addr_ = ip;
+}
+
+isc::dhcp::ParserPtr
+RelayInfoParser::createConfigParser(const std::string& parameter) {
+    DhcpConfigParser* parser = NULL;
+    if (parameter.compare("ip-address") == 0) {
+        parser = new StringParser(parameter, string_values_);
+    } else {
+        isc_throw(NotImplemented,
+                  "parser error: RelayInfoParser parameter not supported: "
+                  << parameter);
+    }
+
+    return (isc::dhcp::ParserPtr(parser));
+}
+
+void
+RelayInfoParser::commit() {
+    *storage_ = local_;
+}
+
+//****************************** PoolParser ********************************
 PoolParser::PoolParser(const std::string&,  PoolStoragePtr pools)
         :pools_(pools) {
 

+ 40 - 0
src/lib/dhcpsrv/dhcp_parsers.h

@@ -754,6 +754,46 @@ protected:
     PoolStorage local_pools_;
 };
 
+/// @brief parser for additional relay information
+///
+/// This concrete parser handles RelayInfo structure defintions.
+/// So far that structure holds only relay IP (v4 or v6) address, but it
+/// is expected that the number of parameters will increase over time.
+///
+/// It is useful for parsing Dhcp<4/6>/subnet<4/6>[x]/relay parameters.
+class RelayInfoParser : public DhcpConfigParser {
+public:
+
+    /// @brief constructor
+    /// @param dummy first argument is ignored, all Parser constructors
+    /// accept string as first argument.
+    /// @param relay_info is the storage in which to store the parsed
+    /// relay information upon "commit".
+    RelayInfoParser(const std::string& dummy,
+                    const isc::dhcp::Subnet::RelayInfoPtr& relay_info,
+                    const asiolink::IOAddress& default_addr);
+
+    /// @brief parses the actual relay parameters
+    /// @param relay_info JSON strcture holding relay parameters to parse
+    virtual void build(isc::data::ConstElementPtr relay_info);
+
+    /// @brief stores parsed info in relay_info
+    virtual void commit();
+
+protected:
+    isc::dhcp::ParserPtr
+    createConfigParser(const std::string& parser);
+
+    /// Parsed data will be stored there on commit()
+    isc::dhcp::Subnet::RelayInfoPtr storage_;
+
+    /// Local storage information (for temporary values)
+    isc::dhcp::Subnet::RelayInfo local_;
+
+    /// Storage for subnet-specific string values.
+    StringStoragePtr string_values_;
+};
+
 /// @brief this class parses a single subnet
 ///
 /// This class parses the whole subnet definition. It creates parsers

+ 4 - 1
src/lib/dhcpsrv/subnet.h

@@ -154,7 +154,7 @@ public:
         >
     > OptionContainer;
 
-    // Pointer to the OptionContainer object.
+    /// Pointer to the OptionContainer object.
     typedef boost::shared_ptr<OptionContainer> OptionContainerPtr;
     /// Type of the index #1 - option type.
     typedef OptionContainer::nth_index<1>::type OptionContainerTypeIndex;
@@ -183,6 +183,9 @@ public:
         isc::asiolink::IOAddress addr_;
     };
 
+    /// Pointer to the RelayInfo structure
+    typedef boost::shared_ptr<Subnet::RelayInfo> RelayInfoPtr;
+
     /// @brief checks if specified address is in range
     bool inRange(const isc::asiolink::IOAddress& addr) const;
 

+ 47 - 0
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc

@@ -1267,3 +1267,50 @@ TEST_F(ParserContextTest, copyConstruct) {
 TEST_F(ParserContextTest, copyConstructNull) {
     testCopyAssignmentNull(true);
 }
+
+/// @brief Checks that a valid relay info structure for IPv4 can be handled
+TEST_F(ParseConfigTest, validRelayInfo4) {
+
+    // Relay information structure. Very simple for now.
+    std::string config_str =
+        "    {"
+        "     \"ip-address\" : \"192.0.2.1\""
+        "    }";
+    ElementPtr json = Element::fromJSON(config_str);
+
+    // We need to set the default ip-address to something.
+    Subnet::RelayInfoPtr result(new Subnet::RelayInfo(asiolink::IOAddress("0.0.0.0")));
+
+    boost::shared_ptr<RelayInfoParser> parser;
+
+    // Subnet4 parser will pass 0.0.0.0 to the RelayInfoParser
+    EXPECT_NO_THROW(parser.reset(new RelayInfoParser("ignored", result,
+                                      asiolink::IOAddress("0.0.0.0"))));
+    EXPECT_NO_THROW(parser->build(json));
+    EXPECT_NO_THROW(parser->commit());
+
+    EXPECT_EQ("192.0.2.1", result->addr_.toText());
+}
+
+/// @brief Checks that a valid relay info structure for IPv6 can be handled
+TEST_F(ParseConfigTest, validRelayInfo6) {
+
+    // Relay information structure. Very simple for now.
+    std::string config_str =
+        "    {"
+        "     \"ip-address\" : \"2001:db8::1\""
+        "    }";
+    ElementPtr json = Element::fromJSON(config_str);
+
+    // We need to set the default ip-address to something.
+    Subnet::RelayInfoPtr result(new Subnet::RelayInfo(asiolink::IOAddress("::")));
+
+    boost::shared_ptr<RelayInfoParser> parser;
+    // Subnet4 parser will pass :: to the RelayInfoParser
+    EXPECT_NO_THROW(parser.reset(new RelayInfoParser("ignored", result,
+                                      asiolink::IOAddress("::"))));
+    EXPECT_NO_THROW(parser->build(json));
+    EXPECT_NO_THROW(parser->commit());
+
+    EXPECT_EQ("2001:db8::1", result->addr_.toText());
+}