mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 06:25:34 +00:00
[2491] Create Status Code option using an option definition.
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#include <dhcp/option6_iaaddr.h>
|
#include <dhcp/option6_iaaddr.h>
|
||||||
#include <dhcp/option6_iaaddr.h>
|
#include <dhcp/option6_iaaddr.h>
|
||||||
#include <dhcp/option6_int_array.h>
|
#include <dhcp/option6_int_array.h>
|
||||||
|
#include <dhcp/option_custom.h>
|
||||||
#include <dhcp/pkt6.h>
|
#include <dhcp/pkt6.h>
|
||||||
#include <dhcp6/dhcp6_log.h>
|
#include <dhcp6/dhcp6_log.h>
|
||||||
#include <dhcp6/dhcp6_srv.h>
|
#include <dhcp6/dhcp6_srv.h>
|
||||||
@@ -348,13 +349,18 @@ void Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionPtr Dhcpv6Srv::createStatusCode(uint16_t code, const std::string& text) {
|
OptionPtr Dhcpv6Srv::createStatusCode(uint16_t code, const std::string& text) {
|
||||||
|
OptionDefinitionPtr status_code_def =
|
||||||
|
LibDHCP::getOptionDef(Option::V6, D6O_STATUS_CODE);
|
||||||
|
assert(status_code_def);
|
||||||
|
|
||||||
// @todo: Implement Option6_StatusCode and rewrite this code here
|
boost::shared_ptr<OptionCustom> option_status =
|
||||||
vector<uint8_t> data(text.c_str(), text.c_str() + text.length());
|
boost::dynamic_pointer_cast<
|
||||||
data.insert(data.begin(), static_cast<uint8_t>(code % 256));
|
OptionCustom>(status_code_def->optionFactory(Option::V6, D6O_STATUS_CODE));
|
||||||
data.insert(data.begin(), static_cast<uint8_t>(code >> 8));
|
assert(option_status);
|
||||||
OptionPtr status(new Option(Option::V6, D6O_STATUS_CODE, data));
|
|
||||||
return (status);
|
option_status->writeInteger<uint16_t>(code, 0);
|
||||||
|
option_status->writeString(text, 1);
|
||||||
|
return (option_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
Subnet6Ptr Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
|
Subnet6Ptr Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) {
|
||||||
|
@@ -801,12 +801,23 @@ TEST_F(Dhcpv6SrvTest, StatusCode) {
|
|||||||
ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
|
ASSERT_NO_THROW( srv.reset(new NakedDhcpv6Srv(0)) );
|
||||||
|
|
||||||
// a dummy content for client-id
|
// a dummy content for client-id
|
||||||
uint8_t expected[] = {0x0, 0x3, 0x41, 0x42, 0x43, 0x44, 0x45};
|
uint8_t expected[] = {
|
||||||
OptionBuffer exp(expected, expected + sizeof(expected));
|
0x0, 0xD, // option code = 14
|
||||||
|
0x0, 0x7, // option length = 7
|
||||||
|
0x0, 0x3, // status code = 3
|
||||||
|
0x41, 0x42, 0x43, 0x44, 0x45 // string value ABCDE
|
||||||
|
};
|
||||||
|
// Create the option.
|
||||||
OptionPtr status = srv->createStatusCode(3, "ABCDE");
|
OptionPtr status = srv->createStatusCode(3, "ABCDE");
|
||||||
|
// Allocate an output buffer. We will store the option
|
||||||
EXPECT_TRUE(status->getData() == exp);
|
// in wire format here.
|
||||||
|
OutputBuffer buf(sizeof(expected));
|
||||||
|
// Prepare the wire format.
|
||||||
|
ASSERT_NO_THROW(status->pack(buf));
|
||||||
|
// Check that the option buffer has valid length (option header + data).
|
||||||
|
ASSERT_EQ(sizeof(expected), buf.getLength());
|
||||||
|
// Verify the contents of the option.
|
||||||
|
EXPECT_EQ(0, memcmp(expected, buf.getData(), sizeof(expected)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test verifies if the selectSubnet() method works as expected.
|
// This test verifies if the selectSubnet() method works as expected.
|
||||||
|
@@ -32,7 +32,17 @@ OptionCustom::OptionCustom(const OptionDefinition& def,
|
|||||||
const OptionBuffer& data)
|
const OptionBuffer& data)
|
||||||
: Option(u, def.getCode(), data.begin(), data.end()),
|
: Option(u, def.getCode(), data.begin(), data.end()),
|
||||||
definition_(def) {
|
definition_(def) {
|
||||||
createBuffers(data_);
|
// It is possible that no data is provided if an option
|
||||||
|
// is being created on a server side. In such case a bunch
|
||||||
|
// of buffers with default values is first created and then
|
||||||
|
// the values are replaced using writeXXX functions. Thus
|
||||||
|
// we need to detect that no data has been specified and
|
||||||
|
// take a different code path.
|
||||||
|
if (!data_.empty()) {
|
||||||
|
createBuffers(data_);
|
||||||
|
} else {
|
||||||
|
createBuffers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionCustom::OptionCustom(const OptionDefinition& def,
|
OptionCustom::OptionCustom(const OptionDefinition& def,
|
||||||
|
@@ -136,7 +136,7 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type,
|
|||||||
return (factoryIAAddr6(type, begin, end));
|
return (factoryIAAddr6(type, begin, end));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (OptionPtr(new OptionCustom(*this, u, begin, end)));
|
return (OptionPtr(new OptionCustom(*this, u, OptionBuffer(begin, end))));
|
||||||
|
|
||||||
} catch (const Exception& ex) {
|
} catch (const Exception& ex) {
|
||||||
isc_throw(InvalidOptionValue, ex.what());
|
isc_throw(InvalidOptionValue, ex.what());
|
||||||
|
@@ -246,7 +246,7 @@ public:
|
|||||||
/// @throw MalformedOptionDefinition if option definition is invalid.
|
/// @throw MalformedOptionDefinition if option definition is invalid.
|
||||||
/// @throw InvalidOptionValue if data for the option is invalid.
|
/// @throw InvalidOptionValue if data for the option is invalid.
|
||||||
OptionPtr optionFactory(Option::Universe u, uint16_t type,
|
OptionPtr optionFactory(Option::Universe u, uint16_t type,
|
||||||
const OptionBuffer& buf) const;
|
const OptionBuffer& buf = OptionBuffer()) const;
|
||||||
|
|
||||||
/// @brief Option factory.
|
/// @brief Option factory.
|
||||||
///
|
///
|
||||||
|
Reference in New Issue
Block a user