return (msg);
}
+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);
if (ciaddr_.isSpecified()) {
context_.query_->setCiaddr(ciaddr_.get());
}
+
+ appendExtraOptions();
+
// Send the message to the server.
sendMsg(context_.query_);
// Expect response.
}
}
+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
/// 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()
+ ///
+ /// Copies options from extra_options_ into outgoing message.
+ void appendExtraOptions();
/// @brief Creates and adds Requested IP Address option to the client's
/// query.
/// @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
#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>
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());
+}
+
}; // end of anonymous namespace
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);
}
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
return (duid_);
}
+ /// @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.
/// @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_;
};
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.