Browse Source

[4206] Unit-tests implemented for empty duid/client-id.

Tomek Mrugalski 9 years ago
parent
commit
d918039035

+ 18 - 0
src/bin/dhcp4/tests/dhcp4_client.cc

@@ -213,6 +213,17 @@ Dhcp4Client::createMsg(const uint8_t msg_type) {
 }
 
 void
+Dhcp4Client::appendExtraOptions() {
+    // If there are any custom options specified, add them all to the message.
+    if (!extra_options_.empty()) {
+        for (OptionCollection::iterator opt = extra_options_.begin();
+             opt != extra_options_.end(); ++opt) {
+            context_.query_->addOption(opt->second);
+        }
+    }
+}
+
+void
 Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
     context_.query_ = createMsg(DHCPDISCOVER);
     // Request options if any.
@@ -228,6 +239,8 @@ Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
     if (ciaddr_.isSpecified()) {
         context_.query_->setCiaddr(ciaddr_.get());
     }
+    appendExtraOptions();
+
     // Send the message to the server.
     sendMsg(context_.query_);
     // Expect response.
@@ -485,6 +498,11 @@ Dhcp4Client::setHWAddress(const std::string& hwaddr_str) {
     }
 }
 
+void
+Dhcp4Client::addExtraOption(const OptionPtr& opt) {
+    extra_options_.insert(std::make_pair(opt->getType(), opt));
+}
+
 } // end of namespace isc::dhcp::test
 } // end of namespace isc::dhcp
 } // end of namespace isc

+ 11 - 0
src/bin/dhcp4/tests/dhcp4_client.h

@@ -355,7 +355,16 @@ public:
     /// in the client's messages.
     isc::util::OptionalValue<asiolink::IOAddress> ciaddr_;
 
+    /// @brief Adds extra option (an option the client will always send)
+    ///
+    /// @param opt additional option to be sent
+    void addExtraOption(const OptionPtr& opt);
+
 private:
+    /// @brief Appends extra options, previously added with addExtraOption()
+    ///
+    /// @brief Copies options from extra_options_ into outgoing message
+    void appendExtraOptions();
 
     /// @brief Creates and adds Requested IP Address option to the client's
     /// query.
@@ -467,6 +476,8 @@ private:
     /// @brief Enable relaying messages to the server.
     bool use_relay_;
 
+    /// @brief Extra options the client will send.
+    OptionCollection extra_options_;
 };
 
 } // end of namespace isc::dhcp::test

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

@@ -19,6 +19,7 @@
 #include <cc/command_interpreter.h>
 #include <config/command_mgr.h>
 #include <dhcp4/tests/dhcp4_test_utils.h>
+#include <dhcp4/tests/dhcp4_client.h>
 #include <dhcp/tests/pkt_captures.h>
 #include <dhcp/dhcp4.h>
 #include <dhcp/iface_mgr.h>
@@ -2659,6 +2660,29 @@ TEST_F(Dhcpv4SrvTest, statisticsUnknownRcvd) {
     EXPECT_EQ(1, drop_stat->getInteger().first);
 }
 
+// This test verifies that the server is able to handle an empty client-id
+// in incoming client message.
+TEST_F(Dhcpv4SrvTest, emptyClientId) {
+    Dhcp4Client client;
+
+    EXPECT_NO_THROW(configure(CONFIGS[0], *client.getServer()));
+
+    // Tell the client to not send client-id on its own.
+    client.includeClientId("");
+
+    // Instead, tell him to send this extra option, which happens to be
+    // an empty client-id.
+    OptionPtr empty_client_id(new Option(Option::V4, DHO_DHCP_CLIENT_IDENTIFIER));
+    client.addExtraOption(empty_client_id);
+
+    // Let's check whether the server is able to process this packet without
+    // throwing any exceptions. We don't care whether the server sent any
+    // responses or not. The goal is to check that the server didn't throw
+    // any exceptions.
+    EXPECT_NO_THROW(client.doDORA());
+}
+
+
 /// @todo: Implement proper tests for MySQL lease/host database,
 ///        see ticket #4214.
 

+ 13 - 1
src/bin/dhcp6/tests/dhcp6_client.cc

@@ -369,6 +369,7 @@ Dhcp6Client::createMsg(const uint8_t msg_type) {
     if (use_client_id_) {
         msg->addOption(getClientId());
     }
+
     if (use_oro_) {
         OptionUint16ArrayPtr oro(new OptionUint16Array(Option::V6, D6O_ORO));
         oro->setValues(oro_);
@@ -376,6 +377,14 @@ Dhcp6Client::createMsg(const uint8_t msg_type) {
         msg->addOption(oro);
     };
 
+    // If there are any custom options specified, add them all to the message.
+    if (!extra_options_.empty()) {
+        for (OptionCollection::iterator opt = extra_options_.begin();
+             opt != extra_options_.end(); ++opt) {
+            msg->addOption(opt->second);
+        }
+    }
+
     return (msg);
 }
 
@@ -758,7 +767,10 @@ Dhcp6Client::useFQDN(const uint8_t flags, const std::string& fqdn_name,
     fqdn_.reset(new Option6ClientFqdn(flags, fqdn_name, fqdn_type));
 }
 
-
+void
+Dhcp6Client::addExtraOption(const OptionPtr& opt) {
+    extra_options_.insert(std::make_pair(opt->getType(), opt));
+}
 
 } // end of namespace isc::dhcp::test
 } // end of namespace isc::dhcp

+ 8 - 0
src/bin/dhcp6/tests/dhcp6_client.h

@@ -579,6 +579,11 @@ public:
     void
     generateIAFromLeases(const Pkt6Ptr& query);
 
+    /// @brief Adds extra option (an option the client will always send)
+    ///
+    /// @param opt additional option to be sent
+    void addExtraOption(const OptionPtr& opt);
+
 private:
 
     /// @brief Applies the new leases for the client.
@@ -752,6 +757,9 @@ private:
     /// @brief forced (Overridden) value of the server-id option (may be NULL)
     OptionPtr forced_server_id_;
 
+    /// @brief Extra options the client will send.
+    OptionCollection extra_options_;
+
     /// @brief FQDN requested by the client.
     Option6ClientFqdnPtr fqdn_;
 

+ 71 - 0
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -2734,6 +2734,77 @@ TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
     EXPECT_EQ(1, recv_drop->getInteger().first);
 }
 
+// This test verifies that the server is able to handle an empty DUID (client-id)
+// in incoming client message.
+TEST_F(Dhcpv6SrvTest, emptyClientId) {
+    Dhcp6Client client;
+
+    // The following configuration enables RSOO options: 110 and 120.
+    // It also configures the server with option 120 which should
+    // "override" the option 120 sent in the RSOO by the relay.
+    string config =
+        "{"
+        "    \"preferred-lifetime\": 3000,"
+        "    \"rebind-timer\": 2000, "
+        "    \"renew-timer\": 1000, "
+        "    \"subnet6\": [ { "
+        "        \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
+        "        \"subnet\": \"2001:db8::/48\" "
+        "     } ],"
+        "    \"valid-lifetime\": 4000"
+        "}";
+
+    EXPECT_NO_THROW(configure(config, *client.getServer()));
+
+    // Tell the client to not send client-id on its own.
+    client.useClientId(false);
+
+    // Instead, tell him to send this extra option, which happens to be
+    // an empty client-id.
+    OptionPtr empty_client_id(new Option(Option::V6, D6O_CLIENTID));
+    client.addExtraOption(empty_client_id);
+
+    // Let's check whether the server is able to process this packet without
+    // throwing any exceptions. We don't care whether the server sent any
+    // responses or not. The goal is to check that the server didn't throw
+    // any exceptions.
+    EXPECT_NO_THROW(client.doSARR());
+}
+
+// This test verifies that the server is able to handle an empty DUID (server-id)
+// in incoming client message.
+TEST_F(Dhcpv6SrvTest, emptyServerId) {
+    Dhcp6Client client;
+
+    // The following configuration enables RSOO options: 110 and 120.
+    // It also configures the server with option 120 which should
+    // "override" the option 120 sent in the RSOO by the relay.
+    string config =
+        "{"
+        "    \"preferred-lifetime\": 3000,"
+        "    \"rebind-timer\": 2000, "
+        "    \"renew-timer\": 1000, "
+        "    \"subnet6\": [ { "
+        "        \"pools\": [ { \"pool\": \"2001:db8::/64\" } ],"
+        "        \"subnet\": \"2001:db8::/48\" "
+        "     } ],"
+        "    \"valid-lifetime\": 4000"
+        "}";
+
+    EXPECT_NO_THROW(configure(config, *client.getServer()));
+
+    // Tell the client to use this specific server-id.
+    OptionPtr empty_server_id(new Option(Option::V6, D6O_SERVERID));
+    client.useServerId(empty_server_id);
+
+    // Let's check whether the server is able to process this packet without
+    // throwing any exceptions. We don't care whether the server sent any
+    // responses or not. The goal is to check that the server didn't throw
+    // any exceptions.
+    EXPECT_NO_THROW(client.doSARR());
+}
+
+
 /// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
 /// to call processX() methods.