mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 06:25:34 +00:00
[master] Merge branch 'trac4206' (empty DUID/client-id fix)
This commit is contained in:
@@ -457,6 +457,11 @@ This error message is issued when preparing an on-wire format of the packet
|
|||||||
has failed. The first argument identifies the client and the DHCP transaction.
|
has failed. The first argument identifies the client and the DHCP transaction.
|
||||||
The second argument includes the error string.
|
The second argument includes the error string.
|
||||||
|
|
||||||
|
% DHCP4_PACKET_PROCESS_EXCEPTION exception occurred during packet processing: %1
|
||||||
|
This error message indicates that an exception was raised during packet processing
|
||||||
|
that was not caught by other, more specific exception handlers. This packet will
|
||||||
|
be dropped and the server will continue operation.
|
||||||
|
|
||||||
% DHCP4_PACKET_RECEIVED %1: %2 (type %3) received from %4 to %5 on interface %6
|
% DHCP4_PACKET_RECEIVED %1: %2 (type %3) received from %4 to %5 on interface %6
|
||||||
A debug message noting that the server has received the specified type of
|
A debug message noting that the server has received the specified type of
|
||||||
packet on the specified interface. The first argument specifies the
|
packet on the specified interface. The first argument specifies the
|
||||||
|
@@ -427,6 +427,8 @@ Dhcpv4Srv::run() {
|
|||||||
Pkt4Ptr query;
|
Pkt4Ptr query;
|
||||||
Pkt4Ptr rsp;
|
Pkt4Ptr rsp;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uint32_t timeout = 1000;
|
uint32_t timeout = 1000;
|
||||||
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT).arg(timeout);
|
LOG_DEBUG(packet4_logger, DBG_DHCP4_DETAIL, DHCP4_BUFFER_WAIT).arg(timeout);
|
||||||
@@ -787,6 +789,19 @@ Dhcpv4Srv::run() {
|
|||||||
.arg(rsp->getLabel())
|
.arg(rsp->getLabel())
|
||||||
.arg(e.what());
|
.arg(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// General catch-all exception that are not caught by more specific
|
||||||
|
// catches. This one is for exceptions derived from std::exception.
|
||||||
|
LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION)
|
||||||
|
.arg(e.what());
|
||||||
|
} catch (...) {
|
||||||
|
// General catch-all exception that are not caught by more specific
|
||||||
|
// catches. This one is for other exceptions, not derived from
|
||||||
|
// std::exception.
|
||||||
|
LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION)
|
||||||
|
.arg("an unknown exception not derived from std::exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
|
@@ -212,6 +212,17 @@ Dhcp4Client::createMsg(const uint8_t msg_type) {
|
|||||||
return (msg);
|
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
|
void
|
||||||
Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
|
Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
|
||||||
context_.query_ = createMsg(DHCPDISCOVER);
|
context_.query_ = createMsg(DHCPDISCOVER);
|
||||||
@@ -228,6 +239,8 @@ Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
|
|||||||
if (ciaddr_.isSpecified()) {
|
if (ciaddr_.isSpecified()) {
|
||||||
context_.query_->setCiaddr(ciaddr_.get());
|
context_.query_->setCiaddr(ciaddr_.get());
|
||||||
}
|
}
|
||||||
|
appendExtraOptions();
|
||||||
|
|
||||||
// Send the message to the server.
|
// Send the message to the server.
|
||||||
sendMsg(context_.query_);
|
sendMsg(context_.query_);
|
||||||
// Expect response.
|
// 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::test
|
||||||
} // end of namespace isc::dhcp
|
} // end of namespace isc::dhcp
|
||||||
} // end of namespace isc
|
} // end of namespace isc
|
||||||
|
@@ -355,7 +355,16 @@ public:
|
|||||||
/// in the client's messages.
|
/// in the client's messages.
|
||||||
isc::util::OptionalValue<asiolink::IOAddress> ciaddr_;
|
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:
|
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
|
/// @brief Creates and adds Requested IP Address option to the client's
|
||||||
/// query.
|
/// query.
|
||||||
@@ -467,6 +476,8 @@ private:
|
|||||||
/// @brief Enable relaying messages to the server.
|
/// @brief Enable relaying messages to the server.
|
||||||
bool use_relay_;
|
bool use_relay_;
|
||||||
|
|
||||||
|
/// @brief Extra options the client will send.
|
||||||
|
OptionCollection extra_options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace isc::dhcp::test
|
} // end of namespace isc::dhcp::test
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
#include <config/command_mgr.h>
|
#include <config/command_mgr.h>
|
||||||
#include <dhcp4/tests/dhcp4_test_utils.h>
|
#include <dhcp4/tests/dhcp4_test_utils.h>
|
||||||
|
#include <dhcp4/tests/dhcp4_client.h>
|
||||||
#include <dhcp/tests/pkt_captures.h>
|
#include <dhcp/tests/pkt_captures.h>
|
||||||
#include <dhcp/dhcp4.h>
|
#include <dhcp/dhcp4.h>
|
||||||
#include <dhcp/iface_mgr.h>
|
#include <dhcp/iface_mgr.h>
|
||||||
@@ -2659,6 +2660,31 @@ TEST_F(Dhcpv4SrvTest, statisticsUnknownRcvd) {
|
|||||||
EXPECT_EQ(1, drop_stat->getInteger().first);
|
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) {
|
||||||
|
IfaceMgrTestConfig test_config(true);
|
||||||
|
IfaceMgr::instance().openSockets4();
|
||||||
|
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,
|
/// @todo: Implement proper tests for MySQL lease/host database,
|
||||||
/// see ticket #4214.
|
/// see ticket #4214.
|
||||||
|
|
||||||
|
@@ -425,6 +425,11 @@ because packets of this type must be sent to multicast. The first argument
|
|||||||
specifies the client and transaction identification information, the
|
specifies the client and transaction identification information, the
|
||||||
second argument specifies packet type.
|
second argument specifies packet type.
|
||||||
|
|
||||||
|
% DHCP6_PACKET_PROCESS_EXCEPTION exception occurred during packet processing: %1
|
||||||
|
This error message indicates that an exception was raised during packet processing
|
||||||
|
that was not caught by other, more specific exception handlers. This packet will
|
||||||
|
be dropped and the server will continue operation.
|
||||||
|
|
||||||
% DHCP6_PACKET_PROCESS_FAIL processing of %1 message received from %2 failed: %3
|
% DHCP6_PACKET_PROCESS_FAIL processing of %1 message received from %2 failed: %3
|
||||||
This is a general catch-all message indicating that the processing of the
|
This is a general catch-all message indicating that the processing of the
|
||||||
specified packet type from the indicated address failed. The reason is given in the
|
specified packet type from the indicated address failed. The reason is given in the
|
||||||
|
@@ -308,6 +308,8 @@ bool Dhcpv6Srv::run() {
|
|||||||
Pkt6Ptr query;
|
Pkt6Ptr query;
|
||||||
Pkt6Ptr rsp;
|
Pkt6Ptr rsp;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uint32_t timeout = 1000;
|
uint32_t timeout = 1000;
|
||||||
LOG_DEBUG(packet6_logger, DBG_DHCP6_DETAIL, DHCP6_BUFFER_WAIT).arg(timeout);
|
LOG_DEBUG(packet6_logger, DBG_DHCP6_DETAIL, DHCP6_BUFFER_WAIT).arg(timeout);
|
||||||
@@ -701,6 +703,18 @@ bool Dhcpv6Srv::run() {
|
|||||||
.arg(e.what());
|
.arg(e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
// General catch-all standard exceptions that are not caught by more
|
||||||
|
// specific catches.
|
||||||
|
LOG_ERROR(packet6_logger, DHCP6_PACKET_PROCESS_EXCEPTION)
|
||||||
|
.arg(e.what());
|
||||||
|
} catch (...) {
|
||||||
|
// General catch-all non-standard exception that are not caught
|
||||||
|
// by more specific catches.
|
||||||
|
LOG_ERROR(packet6_logger, DHCP6_PACKET_PROCESS_EXCEPTION)
|
||||||
|
.arg("an unknown exception not derived from std::exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
|
@@ -369,6 +369,7 @@ Dhcp6Client::createMsg(const uint8_t msg_type) {
|
|||||||
if (use_client_id_) {
|
if (use_client_id_) {
|
||||||
msg->addOption(getClientId());
|
msg->addOption(getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_oro_) {
|
if (use_oro_) {
|
||||||
OptionUint16ArrayPtr oro(new OptionUint16Array(Option::V6, D6O_ORO));
|
OptionUint16ArrayPtr oro(new OptionUint16Array(Option::V6, D6O_ORO));
|
||||||
oro->setValues(oro_);
|
oro->setValues(oro_);
|
||||||
@@ -376,6 +377,14 @@ Dhcp6Client::createMsg(const uint8_t msg_type) {
|
|||||||
msg->addOption(oro);
|
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);
|
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));
|
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::test
|
||||||
} // end of namespace isc::dhcp
|
} // end of namespace isc::dhcp
|
||||||
|
@@ -579,6 +579,11 @@ public:
|
|||||||
void
|
void
|
||||||
generateIAFromLeases(const Pkt6Ptr& query);
|
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:
|
private:
|
||||||
|
|
||||||
/// @brief Applies the new leases for the client.
|
/// @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)
|
/// @brief forced (Overridden) value of the server-id option (may be NULL)
|
||||||
OptionPtr forced_server_id_;
|
OptionPtr forced_server_id_;
|
||||||
|
|
||||||
|
/// @brief Extra options the client will send.
|
||||||
|
OptionCollection extra_options_;
|
||||||
|
|
||||||
/// @brief FQDN requested by the client.
|
/// @brief FQDN requested by the client.
|
||||||
Option6ClientFqdnPtr fqdn_;
|
Option6ClientFqdnPtr fqdn_;
|
||||||
|
|
||||||
|
@@ -2734,6 +2734,77 @@ TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
|
|||||||
EXPECT_EQ(1, recv_drop->getInteger().first);
|
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
|
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
|
||||||
/// to call processX() methods.
|
/// to call processX() methods.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user