Browse Source

[2591] Append requested options to the OFFER message.

Marcin Siodelski 12 years ago
parent
commit
a0ac798d24
3 changed files with 56 additions and 15 deletions
  1. 37 13
      src/bin/dhcp4/dhcp4_srv.cc
  2. 3 2
      src/bin/dhcp4/dhcp4_srv.h
  3. 16 0
      src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

+ 37 - 13
src/bin/dhcp4/dhcp4_srv.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -17,6 +17,7 @@
 #include <dhcp/iface_mgr.h>
 #include <dhcp/option4_addrlst.h>
 #include <dhcp/option_int.h>
+#include <dhcp/option_int_array.h>
 #include <dhcp/pkt4.h>
 #include <dhcp/duid.h>
 #include <dhcp/hwaddr.h>
@@ -233,18 +234,41 @@ void Dhcpv4Srv::appendDefaultOptions(Pkt4Ptr& msg, uint8_t msg_type) {
 }
 
 
-void Dhcpv4Srv::appendRequestedOptions(Pkt4Ptr& msg) {
-    OptionPtr opt;
+void Dhcpv4Srv::appendRequestedOptions(const Pkt4Ptr& question, Pkt4Ptr& msg) {
+
+    // Get the subnet relevant for the client. We will need it
+    // to get the options associated with it.
+    Subnet4Ptr subnet = selectSubnet(question);
+    // If we can't find the subnet for the client there is no way
+    // to get the options to be sent to a client. We don't log an
+    // error because it will be logged by the assignLease method
+    // anyway.
+    if (!subnet) {
+        return;
+    }
 
-    // Domain name (type 15)
-    vector<uint8_t> domain(HARDCODED_DOMAIN_NAME.begin(), HARDCODED_DOMAIN_NAME.end());
-    opt = OptionPtr(new Option(Option::V4, DHO_DOMAIN_NAME, domain));
-    msg->addOption(opt);
-    // TODO: Add Option_String class
+    // try to get the 'Parameter Request List' option which holds the
+    // codes of requested options.
+    OptionUint8ArrayPtr option_prl = boost::dynamic_pointer_cast<
+        OptionUint8Array>(question->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST));
+    // If there is no PRL option in the message from the client then
+    // there is nothing to do.
+    if (!option_prl) {
+        return;
+    }
 
-    // DNS servers (type 6)
-    opt = OptionPtr(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS, IOAddress(HARDCODED_DNS_SERVER)));
-    msg->addOption(opt);
+    // Get the codes of requested options.
+    const std::vector<uint8_t>& requested_opts = option_prl->getValues();
+    // For each requested option code get the instance of the option
+    // to be returned to the client.
+    for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
+         opt != requested_opts.end(); ++opt) {
+        Subnet::OptionDescriptor desc =
+            subnet->getOptionDescriptor("dhcp4", *opt);
+        if (desc.option) {
+            msg->addOption(desc.option);
+        }
+    }
 }
 
 void Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
@@ -358,7 +382,7 @@ Pkt4Ptr Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
 
     copyDefaultFields(discover, offer);
     appendDefaultOptions(offer, DHCPOFFER);
-    appendRequestedOptions(offer);
+    appendRequestedOptions(discover, offer);
 
     assignLease(discover, offer);
 
@@ -371,7 +395,7 @@ Pkt4Ptr Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
 
     copyDefaultFields(request, ack);
     appendDefaultOptions(ack, DHCPACK);
-    appendRequestedOptions(ack);
+    appendRequestedOptions(request, ack);
 
     assignLease(request, ack);
 

+ 3 - 2
src/bin/dhcp4/dhcp4_srv.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -173,8 +173,9 @@ protected:
     /// This method assigns options that were requested by client
     /// (sent in PRL) or are enforced by server.
     ///
+    /// @param question DISCOVER or REQUEST message from a client.
     /// @param msg outgoing message (options will be added here)
-    void appendRequestedOptions(Pkt4Ptr& msg);
+    void appendRequestedOptions(const Pkt4Ptr& question, Pkt4Ptr& msg);
 
     /// @brief Assigns a lease and appends corresponding options
     ///

+ 16 - 0
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

@@ -19,6 +19,7 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/option.h>
 #include <dhcp/option4_addrlst.h>
+#include <dhcp/option_custom.h>
 #include <dhcp/option_int_array.h>
 #include <dhcp4/dhcp4_srv.h>
 #include <dhcp4/dhcp4_log.h>
@@ -318,8 +319,21 @@ TEST_F(Dhcpv4SrvTest, processDiscover) {
     // in the OFFER message when requested using 'Parameter
     // Request List' option. Let's configure those options that
     // are returned when requested.
+
+    // dns-servers
+    OptionPtr option_dns_servers(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS));
+    ASSERT_NO_THROW(subnet_->addOption(option_dns_servers, false, "dhcp4"));
+    // domain-name
+    OptionDefinition def("domain-name", DHO_DOMAIN_NAME, OPT_FQDN_TYPE);
+    boost::shared_ptr<OptionCustom>
+        option_domain_name(new OptionCustom(def, Option::V4));
+    option_domain_name->writeFqdn("example.com");
+    OptionPtr opt_domain = boost::dynamic_pointer_cast<Option>(option_domain_name);
+    subnet_->addOption(opt_domain, false, "dhcp4");
+    // log-servers
     OptionPtr option_log_servers(new Option4AddrLst(DHO_LOG_SERVERS));
     ASSERT_NO_THROW(subnet_->addOption(option_log_servers, false, "dhcp4"));
+    // cookie-servers
     OptionPtr option_cookie_servers(new Option4AddrLst(DHO_COOKIE_SERVERS));
     ASSERT_NO_THROW(subnet_->addOption(option_cookie_servers, false, "dhcp4"));
 
@@ -332,6 +346,8 @@ TEST_F(Dhcpv4SrvTest, processDiscover) {
 
     std::vector<uint8_t> opts;
     // Let's request options that have been configured for the subnet.
+    opts.push_back(DHO_DOMAIN_NAME_SERVERS);
+    opts.push_back(DHO_DOMAIN_NAME);
     opts.push_back(DHO_LOG_SERVERS);
     opts.push_back(DHO_COOKIE_SERVERS);
     // Let's also request the option that hasn't been configured. In such