mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-22 01:49:48 +00:00
[#3861] allow containers in vendor options
This commit is contained in:
parent
6a10ce215b
commit
a12da4f9fd
@ -1606,6 +1606,141 @@ TEST_F(VendorOptsTest, vivsoInResponseOnly) {
|
||||
EXPECT_FALSE(cdesc.option_->getOption(2));
|
||||
}
|
||||
|
||||
// Checks that it's possible to have a vivso (125) option in the response
|
||||
// only. Once specific client (Genexis) sends only vendor-class info and
|
||||
// expects the server to include vivso in the response. This test adds
|
||||
// an empty container option (code 193) with 2 suboptions
|
||||
// (code 16 - ipv4-address and code 20 - uint16).
|
||||
TEST_F(VendorOptsTest, vivsoInResponseOnlyComplex) {
|
||||
Dhcp4Client client(srv_);
|
||||
|
||||
// The config defines custom vendor 125 suboption 193 that conveys 2 suboptions:
|
||||
// suboption 16 (ipv4-address) and suboption 20 (uint16).
|
||||
// The client doesn't send vendor 125 option, so normal vendor option
|
||||
// processing is impossible. However, since there's a class defined that
|
||||
// matches client's packets and that class inserts vivso in the response,
|
||||
// Kea should be able to figure out the vendor-id and then also insert
|
||||
// suboption 193 with 2 suboptions: 16 and 20.
|
||||
string config =
|
||||
"{"
|
||||
" \"interfaces-config\": {"
|
||||
" \"interfaces\": [ \"*\" ]"
|
||||
" },"
|
||||
" \"option-def\": ["
|
||||
" {"
|
||||
" \"name\": \"pma-addr\","
|
||||
" \"code\": 16,"
|
||||
" \"type\": \"ipv4-address\","
|
||||
" \"array\": false,"
|
||||
" \"space\": \"vendor-25167-193\""
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"pma-port\","
|
||||
" \"code\": 20,"
|
||||
" \"type\": \"uint16\","
|
||||
" \"array\": false,"
|
||||
" \"space\": \"vendor-25167-193\""
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"pma\","
|
||||
" \"code\": 193,"
|
||||
" \"space\": \"vendor-25167\","
|
||||
" \"type\": \"empty\","
|
||||
" \"array\": false,"
|
||||
" \"encapsulate\": \"vendor-25167-193\","
|
||||
" \"record-types\": \"\""
|
||||
" }"
|
||||
" ],"
|
||||
" \"client-classes\": ["
|
||||
" {"
|
||||
" \"name\": \"cpe_genexis\","
|
||||
" \"test\": \"substring(option[60].hex,0,7) == 'HMC1000'\","
|
||||
" \"option-data\": ["
|
||||
" {"
|
||||
" \"name\": \"vivso-suboptions\","
|
||||
" \"data\": \"25167\""
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"pma-addr\","
|
||||
" \"space\": \"vendor-25167-193\","
|
||||
" \"code\": 16,"
|
||||
" \"data\": \"192.0.3.1\","
|
||||
" \"always-send\": true"
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"pma-port\","
|
||||
" \"space\": \"vendor-25167-193\","
|
||||
" \"code\": 20,"
|
||||
" \"data\": \"300\","
|
||||
" \"always-send\": true"
|
||||
" },"
|
||||
" {"
|
||||
" \"name\": \"pma\","
|
||||
" \"space\": \"vendor-25167\","
|
||||
" \"code\": 193,"
|
||||
" \"always-send\": true"
|
||||
" } ]"
|
||||
" } ],"
|
||||
"\"subnet4\": [ { "
|
||||
" \"id\": 10,"
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.0/25\" } ],"
|
||||
" \"subnet\": \"192.0.2.0/24\", "
|
||||
" \"interface\": \"eth0\" "
|
||||
" } ]"
|
||||
"}";
|
||||
|
||||
EXPECT_NO_THROW(configure(config, *client.getServer()));
|
||||
|
||||
// Add a vendor-class identifier (this matches what Genexis hardware sends)
|
||||
OptionPtr vopt(new OptionString(Option::V4, DHO_VENDOR_CLASS_IDENTIFIER,
|
||||
"HMC1000.v1.3.0-R,Element-P1090,genexis.eu"));
|
||||
client.addExtraOption(vopt);
|
||||
client.requestOptions(DHO_VIVSO_SUBOPTIONS);
|
||||
|
||||
// Let's check whether the server is not able to process this packet
|
||||
// and include vivso with appropriate sub-options
|
||||
EXPECT_NO_THROW(client.doDiscover());
|
||||
ASSERT_TRUE(client.getContext().response_);
|
||||
|
||||
// Check there's a response.
|
||||
OptionPtr rsp = client.getContext().response_->getOption(DHO_VIVSO_SUBOPTIONS);
|
||||
ASSERT_TRUE(rsp);
|
||||
|
||||
// Check that it includes vivso with vendor-id = 25167
|
||||
OptionVendorPtr rsp_vivso = boost::dynamic_pointer_cast<OptionVendor>(rsp);
|
||||
ASSERT_TRUE(rsp_vivso);
|
||||
EXPECT_EQ(rsp_vivso->getVendorId(), 25167);
|
||||
|
||||
// Now check that it contains suboption 193 with appropriate content.
|
||||
OptionPtr subopt193 = rsp_vivso->getOption(193);
|
||||
ASSERT_TRUE(subopt193);
|
||||
|
||||
OptionPtr expected(new Option(Option::V4, 193));
|
||||
Option4AddrLstPtr opt16(new Option4AddrLst(16, IOAddress("192.0.3.1")));
|
||||
boost::shared_ptr<OptionIntArray<uint16_t>> opt20(new OptionIntArray<uint16_t>(Option::V4, 20));
|
||||
opt20->addValue(300);
|
||||
expected->addOption(opt16);
|
||||
expected->addOption(opt20);
|
||||
|
||||
vector<uint8_t> subopt193bin = subopt193->toBinary(false);
|
||||
vector<uint8_t> expectedbin = expected->toBinary(false);
|
||||
ASSERT_EQ(expectedbin, subopt193bin);
|
||||
|
||||
// Check the config was not altered by unwanted side effect
|
||||
// on the vendor option.
|
||||
|
||||
// Get class config:
|
||||
ClientClassDefPtr cdef = CfgMgr::instance().getCurrentCfg()->
|
||||
getClientClassDictionary()->findClass("cpe_genexis");
|
||||
ASSERT_TRUE(cdef);
|
||||
OptionDescriptor cdesc = cdef->getCfgOption()->
|
||||
get(DHCP4_OPTION_SPACE, DHO_VIVSO_SUBOPTIONS);
|
||||
ASSERT_TRUE(cdesc.option_);
|
||||
// If the config was altered these two EXPECT will fail.
|
||||
EXPECT_TRUE(cdesc.option_->getOptions().empty());
|
||||
EXPECT_FALSE(cdesc.option_->getOption(2));
|
||||
}
|
||||
|
||||
// Verifies last resort option 43 is backward compatible
|
||||
TEST_F(VendorOptsTest, option43LastResort) {
|
||||
// If there is no definition for option 43 a last resort
|
||||
|
@ -302,6 +302,15 @@ CfgOption::encapsulateInternal(const std::string& option_space) {
|
||||
for (auto const& opt : *options) {
|
||||
encapsulateInternal(opt.option_);
|
||||
}
|
||||
|
||||
for (auto const& vendor : getVendorIds()) {
|
||||
OptionContainerPtr vendor_options = getAll(vendor);
|
||||
// For each option in the option space we will append sub-options
|
||||
// from the option spaces they encapsulate.
|
||||
for (auto const& opt : *vendor_options) {
|
||||
encapsulateInternal(opt.option_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
x
Reference in New Issue
Block a user