Browse Source

[4626] class parser updated to handle next-server, server-name and boot-file-name

Tomek Mrugalski 8 years ago
parent
commit
e5fbda6985

+ 7 - 1
src/lib/dhcpsrv/client_class_def.cc

@@ -115,8 +115,14 @@ ClientClassDictionary::~ClientClassDictionary() {
 void
 ClientClassDictionary::addClass(const std::string& name,
                                 const ExpressionPtr& match_expr,
-                                const CfgOptionPtr& cfg_option) {
+                                const CfgOptionPtr& cfg_option,
+                                asiolink::IOAddress next_server,
+                                const std::vector<uint8_t>& sname,
+                                const std::vector<uint8_t>& filename) {
     ClientClassDefPtr cclass(new ClientClassDef(name, match_expr, cfg_option));
+    cclass->setNextServer(next_server);
+    cclass->setSname(sname);
+    cclass->setFilename(filename);
     addClass(cclass);
 }
 

+ 28 - 1
src/lib/dhcpsrv/client_class_def.h

@@ -112,6 +112,27 @@ public:
         return (next_server_);
     }
 
+    /// @brief sets the next-server value
+    ///
+    /// @param addr the value to be set
+    void setNextServer(const asiolink::IOAddress& addr) {
+        next_server_ = addr;
+    }
+
+    /// @brief sets the server-name value
+    ///
+    /// @param sname the value to be set
+    void setSname(const std::vector<uint8_t>& sname) {
+        sname_ = sname;
+    }
+
+    /// @brief sets the boot-file-name value
+    ///
+    /// @param filename the value to be set
+    void setFilename(const std::vector<uint8_t>& filename) {
+        filename_ = filename;
+    }
+
     /// @brief returns server-hostname value
     /// @return the vector that contains server-hostname (may be empty if not defined)
     const std::vector<uint8_t>& getSname() const {
@@ -183,12 +204,18 @@ public:
     /// @param name Name to assign to this class
     /// @param match_expr Expression the class will use to determine membership
     /// @param options Collection of options members should be given
+    /// @param next_server next-server value for this class (optional)
+    /// @param sname server-name value for this class (optional)
+    /// @param filename boot-file-name value for this class (optional)
     ///
     /// @throw DuplicateClientClassDef if class already exists within the
     /// dictionary.  See @ref dhcp::ClientClassDef::ClientClassDef() for
     /// others.
     void addClass(const std::string& name, const ExpressionPtr& match_expr,
-                  const CfgOptionPtr& options);
+                  const CfgOptionPtr& options,
+                  asiolink::IOAddress next_server = asiolink::IOAddress("0.0.0.0"),
+                  const std::vector<uint8_t>& sname = std::vector<uint8_t>(),
+                  const std::vector<uint8_t>& filename = std::vector<uint8_t>());
 
     /// @brief Adds a new class to the list
     ///

+ 39 - 0
src/lib/dhcpsrv/parsers/client_class_def_parser.cc

@@ -9,10 +9,14 @@
 #include <dhcpsrv/client_class_def.h>
 #include <dhcpsrv/parsers/client_class_def_parser.h>
 #include <eval/eval_context.h>
+#include <asiolink/io_address.h>
+#include <asiolink/io_error.h>
 
 #include <boost/foreach.hpp>
 
 using namespace isc::data;
+using namespace isc::asiolink;
+using namespace std;
 
 /// @file client_class_def.cc
 ///
@@ -73,6 +77,11 @@ ClientClassDefParser::ClientClassDefParser(const std::string&,
 
 void
 ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
+
+    IOAddress next_server("0.0.0.0");
+    std::vector<uint8_t> sname;
+    std::vector<uint8_t> filename;
+
     // Parse the elements that make up the option definition.
     BOOST_FOREACH(ConfigPair param, class_def_cfg->mapValue()) {
         std::string entry(param.first);
@@ -92,6 +101,36 @@ ClientClassDefParser::build(ConstElementPtr class_def_cfg) {
 
             opts_parser.reset(new OptionDataListParser(entry, options_, family));
             parser = opts_parser;
+        } else if (entry == "next-server") {
+            // Let's parse the next-server field
+            try {
+                next_server = IOAddress(param.second->stringValue());
+            } catch (const IOError& ex) {
+                isc_throw(DhcpConfigError, "Invalid next-server value specified: '"
+                          << param.second << "'");
+            }
+            if (next_server.getFamily() != AF_INET) {
+                isc_throw(DhcpConfigError, "Invalid next-server value: '"
+                          << param.second << "', must be IPv4 address");
+            }
+        } else if (entry == "server-hostname") {
+            string tmp = param.second->stringValue();
+            if (tmp.length() > Pkt4::MAX_SNAME_LEN) {
+                isc_throw(DhcpConfigError, "server-hostname must be at most "
+                          << Pkt4::MAX_SNAME_LEN << " bytes long, it is "
+                          << tmp.length());
+            }
+            sname = vector<uint8_t>(tmp.begin(), tmp.end());
+
+        } else if (entry == "boot-file-name") {
+            string tmp = param.second->stringValue();
+            if (tmp.length() > Pkt4::MAX_FILE_LEN) {
+                isc_throw(DhcpConfigError, "boot-file-name must be at most "
+                          << Pkt4::MAX_FILE_LEN << " bytes long, it is "
+                          << tmp.length());
+            }
+            filename = vector<uint8_t>(tmp.begin(), tmp.end());
+
         } else {
             isc_throw(DhcpConfigError, "invalid parameter '" << entry
                       << "' (" << param.second->getPosition() << ")");