Parcourir la source

[4626] Prototype implementation for fields storage done.

Tomek Mrugalski il y a 8 ans
Parent
commit
9134e71011

+ 45 - 0
src/bin/dhcp4/dhcp4_srv.cc

@@ -1927,6 +1927,51 @@ Dhcpv4Srv::adjustRemoteAddr(Dhcpv4Exchange& ex) {
     }
 }
 
+void
+Dhcpv4Srv::setFixedFields(Dhcpv4Exchange& ex) {
+    Pkt4Ptr query = ex.getQuery();
+    Pkt4Ptr response = ex.getResponse();
+
+    const ClientClasses classes = query->getClasses();
+    if (classes.empty()) {
+        return;
+    }
+
+    // Let's get class definitions
+    const ClientClassDefMapPtr& defs = CfgMgr::instance().getCurrentCfg()->
+        getClientClassDictionary()->getClasses();
+
+    // Now we need to iterate over the classes assigned to the
+    // query packet and find corresponding class defintions for it.
+    for (ClientClasses::const_iterator name = classes.begin();
+         name != classes.end(); ++name) {
+
+        ClientClassDefMap::const_iterator cl = defs->find(*name);
+        if (cl == defs->end()) {
+            // Let's skip classes that don't have definitions. Currently
+            // these are automatic classes VENDOR_CLASS_something, but there
+            // may be other classes assigned under other circumstances, e.g.
+            // by hooks.
+            continue;
+        }
+
+        IOAddress next_server = cl->second->getNextServer();
+        if (!next_server.isV4Zero()) {
+            response->setSiaddr(next_server);
+        }
+
+        const vector<uint8_t>& sname = cl->second->getSname();
+        if (!sname.empty()) {
+            response->setSname(&sname[0], sname.size());
+        }
+
+        const vector<uint8_t>& filename = cl->second->getFilename();
+        if (!filename.empty()) {
+            response->setFile(&filename[0], filename.size());
+        }
+    }
+}
+
 
 OptionPtr
 Dhcpv4Srv::getNetmaskOption(const Subnet4Ptr& subnet) {

+ 11 - 0
src/bin/dhcp4/dhcp4_srv.h

@@ -513,6 +513,17 @@ protected:
     /// @param ex DHCPv4 exchange holding the client's message to be checked.
     void appendBasicOptions(Dhcpv4Exchange& ex);
 
+    /// @brief Sets fixed fields of the outgoing packet.
+    ///
+    /// If the incoming packets belongs to a class and that class defines
+    /// next-server, server-hostname or boot-file-name, we need to set the
+    /// siaddr, sname or filename fields in the outgoing packet. This
+    /// is what this method does.
+    ///
+    /// @param ex DHCPv4 exchange holding the client's message and the server's
+    ///           response to be adjusted.
+    void setFixedFields(Dhcpv4Exchange& ex);
+
     /// @brief Processes Client FQDN and Hostname Options sent by a client.
     ///
     /// Client may send Client FQDN or Hostname option to communicate its name

+ 3 - 2
src/lib/dhcpsrv/client_class_def.cc

@@ -15,7 +15,8 @@ namespace dhcp {
 ClientClassDef::ClientClassDef(const std::string& name,
                                const ExpressionPtr& match_expr,
                                const CfgOptionPtr& cfg_option)
-    : name_(name), match_expr_(match_expr), cfg_option_(cfg_option) {
+    : name_(name), match_expr_(match_expr), cfg_option_(cfg_option),
+      next_server_(asiolink::IOAddress("0.0.0.0")) {
 
     // Name can't be blank
     if (name_.empty()) {
@@ -33,7 +34,7 @@ ClientClassDef::ClientClassDef(const std::string& name,
 
 ClientClassDef::ClientClassDef(const ClientClassDef& rhs)
     : name_(rhs.name_), match_expr_(ExpressionPtr()),
-      cfg_option_(new CfgOption()) {
+      cfg_option_(new CfgOption()), next_server_(asiolink::IOAddress("0.0.0.0")) {
 
     if (rhs.match_expr_) {
         match_expr_.reset(new Expression());

+ 36 - 0
src/lib/dhcpsrv/client_class_def.h

@@ -106,6 +106,24 @@ public:
     /// @brief Provides a convenient text representation of the class
     friend std::ostream& operator<<(std::ostream& os, const ClientClassDef& x);
 
+    /// @brief returns next-server value
+    /// @return next-server value
+    asiolink::IOAddress getNextServer() const {
+        return (next_server_);
+    }
+
+    /// @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 {
+        return (sname_);
+    }
+
+    /// @brief returns boot-file-name value
+    /// @return the vector that contains boot-file-name (may be empty if not defined)
+    const std::vector<uint8_t>& getFilename() const {
+        return (filename_);
+    }
+
 private:
     /// @brief Unique text identifier by which this class is known.
     std::string name_;
@@ -116,6 +134,24 @@ private:
 
     /// @brief The option data configuration for this class
     CfgOptionPtr cfg_option_;
+
+    /// @brief Next server field
+    /// If set by the next-server parameter, this value will be set
+    /// in the siaddr field of the DHCPv4 packet.
+    asiolink::IOAddress next_server_;
+
+    /// @brief server-hostname
+    /// If set by the server-hostname parameter, this value will be
+    /// set in the sname field of the DHCPv4 packet.
+    /// This can be up to 64 octets long.
+    std::vector<uint8_t> sname_;
+
+    /// @brief boot-file-name
+    /// If set by the boot-file-name parameter, this value will be
+    /// set in the file field of the DHCPv4 packet.
+    /// This can be up to 128 octets long.
+    std::vector<uint8_t> filename_;
+
 };
 
 /// @brief a pointer to an ClientClassDef