summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomek Mrugalski <tomasz@isc.org>2016-08-24 13:17:19 +0200
committerTomek Mrugalski <tomasz@isc.org>2016-08-24 13:17:19 +0200
commit9134e71011c9e0b55ac118c2c8811c08e3911c32 (patch)
treeb89edd288982d535e3e6a9ed6c0db0f67778909a
parent[master] Fixed recently introduced cpp-check (diff)
downloadkea-9134e71011c9e0b55ac118c2c8811c08e3911c32.tar.xz
kea-9134e71011c9e0b55ac118c2c8811c08e3911c32.zip
[4626] Prototype implementation for fields storage done.
-rw-r--r--src/bin/dhcp4/dhcp4_srv.cc45
-rw-r--r--src/bin/dhcp4/dhcp4_srv.h11
-rw-r--r--src/lib/dhcpsrv/client_class_def.cc5
-rw-r--r--src/lib/dhcpsrv/client_class_def.h36
4 files changed, 95 insertions, 2 deletions
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 1ef9d7f0f8..aabcda6697 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/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) {
diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h
index 516ec9921f..813e66635c 100644
--- a/src/bin/dhcp4/dhcp4_srv.h
+++ b/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
diff --git a/src/lib/dhcpsrv/client_class_def.cc b/src/lib/dhcpsrv/client_class_def.cc
index 467be6c971..69a1350a55 100644
--- a/src/lib/dhcpsrv/client_class_def.cc
+++ b/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());
diff --git a/src/lib/dhcpsrv/client_class_def.h b/src/lib/dhcpsrv/client_class_def.h
index 0d3b3c2d72..7d005783cd 100644
--- a/src/lib/dhcpsrv/client_class_def.h
+++ b/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