mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 06:25:34 +00:00
[master] Merge branch 'trac3572'
This commit is contained in:
@@ -924,13 +924,21 @@ void
|
|||||||
Dhcpv4Srv::buildCfgOptionList(Dhcpv4Exchange& ex) {
|
Dhcpv4Srv::buildCfgOptionList(Dhcpv4Exchange& ex) {
|
||||||
CfgOptionList& co_list = ex.getCfgOptionList();
|
CfgOptionList& co_list = ex.getCfgOptionList();
|
||||||
|
|
||||||
// First subnet configured options
|
// Retrieve subnet.
|
||||||
Subnet4Ptr subnet = ex.getContext()->subnet_;
|
Subnet4Ptr subnet = ex.getContext()->subnet_;
|
||||||
if (!subnet) {
|
if (!subnet) {
|
||||||
// All methods using the CfgOptionList object return soon when
|
// All methods using the CfgOptionList object return soon when
|
||||||
// there is no subnet so do the same
|
// there is no subnet so do the same
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Firstly, host specific options.
|
||||||
|
const ConstHostPtr& host = ex.getContext()->host_;
|
||||||
|
if (host && !host->getCfgOption4()->empty()) {
|
||||||
|
co_list.push_back(host->getCfgOption4());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Secondly, subnet configured options.
|
||||||
if (!subnet->getCfgOption()->empty()) {
|
if (!subnet->getCfgOption()->empty()) {
|
||||||
co_list.push_back(subnet->getCfgOption());
|
co_list.push_back(subnet->getCfgOption());
|
||||||
}
|
}
|
||||||
|
@@ -89,6 +89,7 @@ dhcp4_unittests_SOURCES += dhcp4_client.cc dhcp4_client.h
|
|||||||
dhcp4_unittests_SOURCES += hooks_unittest.cc
|
dhcp4_unittests_SOURCES += hooks_unittest.cc
|
||||||
dhcp4_unittests_SOURCES += inform_unittest.cc
|
dhcp4_unittests_SOURCES += inform_unittest.cc
|
||||||
dhcp4_unittests_SOURCES += dora_unittest.cc
|
dhcp4_unittests_SOURCES += dora_unittest.cc
|
||||||
|
dhcp4_unittests_SOURCES += host_options_unittest.cc
|
||||||
dhcp4_unittests_SOURCES += release_unittest.cc
|
dhcp4_unittests_SOURCES += release_unittest.cc
|
||||||
dhcp4_unittests_SOURCES += out_of_range_unittest.cc
|
dhcp4_unittests_SOURCES += out_of_range_unittest.cc
|
||||||
dhcp4_unittests_SOURCES += decline_unittest.cc
|
dhcp4_unittests_SOURCES += decline_unittest.cc
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <dhcp/dhcp4.h>
|
#include <dhcp/dhcp4.h>
|
||||||
#include <dhcp/option.h>
|
#include <dhcp/option.h>
|
||||||
#include <dhcp/option_int_array.h>
|
#include <dhcp/option_int_array.h>
|
||||||
|
#include <dhcp/option_vendor.h>
|
||||||
#include <dhcpsrv/lease.h>
|
#include <dhcpsrv/lease.h>
|
||||||
#include <dhcp4/tests/dhcp4_client.h>
|
#include <dhcp4/tests/dhcp4_client.h>
|
||||||
#include <util/range_utilities.h>
|
#include <util/range_utilities.h>
|
||||||
@@ -163,13 +164,19 @@ Dhcp4Client::applyConfiguration() {
|
|||||||
Option4AddrLstPtr opt_log_servers = boost::dynamic_pointer_cast<
|
Option4AddrLstPtr opt_log_servers = boost::dynamic_pointer_cast<
|
||||||
Option4AddrLst>(resp->getOption(DHO_LOG_SERVERS));
|
Option4AddrLst>(resp->getOption(DHO_LOG_SERVERS));
|
||||||
if (opt_log_servers) {
|
if (opt_log_servers) {
|
||||||
config_.log_servers_ = opt_routers->getAddresses();
|
config_.log_servers_ = opt_log_servers->getAddresses();
|
||||||
}
|
}
|
||||||
// Quotes Servers
|
// Quotes Servers
|
||||||
Option4AddrLstPtr opt_quotes_servers = boost::dynamic_pointer_cast<
|
Option4AddrLstPtr opt_quotes_servers = boost::dynamic_pointer_cast<
|
||||||
Option4AddrLst>(resp->getOption(DHO_COOKIE_SERVERS));
|
Option4AddrLst>(resp->getOption(DHO_COOKIE_SERVERS));
|
||||||
if (opt_quotes_servers) {
|
if (opt_quotes_servers) {
|
||||||
config_.quotes_servers_ = opt_dns_servers->getAddresses();
|
config_.quotes_servers_ = opt_quotes_servers->getAddresses();
|
||||||
|
}
|
||||||
|
// Vendor Specific options
|
||||||
|
OptionVendorPtr opt_vendor = boost::dynamic_pointer_cast<
|
||||||
|
OptionVendor>(resp->getOption(DHO_VIVSO_SUBOPTIONS));
|
||||||
|
if (opt_vendor) {
|
||||||
|
config_.vendor_suboptions_ = opt_vendor->getOptions();
|
||||||
}
|
}
|
||||||
// Server Identifier
|
// Server Identifier
|
||||||
OptionCustomPtr opt_serverid = boost::dynamic_pointer_cast<
|
OptionCustomPtr opt_serverid = boost::dynamic_pointer_cast<
|
||||||
@@ -254,6 +261,8 @@ Dhcp4Client::doInform(const bool set_ciaddr) {
|
|||||||
context_.query_ = createMsg(DHCPINFORM);
|
context_.query_ = createMsg(DHCPINFORM);
|
||||||
// Request options if any.
|
// Request options if any.
|
||||||
appendPRL();
|
appendPRL();
|
||||||
|
// Any other options to be sent by a client.
|
||||||
|
appendExtraOptions();
|
||||||
// The client sending a DHCPINFORM message has an IP address obtained
|
// The client sending a DHCPINFORM message has an IP address obtained
|
||||||
// by some other means, e.g. static configuration. The lease which we
|
// by some other means, e.g. static configuration. The lease which we
|
||||||
// are using here is most likely set by the createLease method.
|
// are using here is most likely set by the createLease method.
|
||||||
@@ -368,6 +377,8 @@ Dhcp4Client::doRequest() {
|
|||||||
appendName();
|
appendName();
|
||||||
// Include Client Identifier
|
// Include Client Identifier
|
||||||
appendClientId();
|
appendClientId();
|
||||||
|
// Any other options to be sent by a client.
|
||||||
|
appendExtraOptions();
|
||||||
// Send the message to the server.
|
// Send the message to the server.
|
||||||
sendMsg(context_.query_);
|
sendMsg(context_.query_);
|
||||||
// Expect response.
|
// Expect response.
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <dhcp/hwaddr.h>
|
#include <dhcp/hwaddr.h>
|
||||||
|
#include <dhcp/option.h>
|
||||||
#include <dhcp/pkt4.h>
|
#include <dhcp/pkt4.h>
|
||||||
#include <dhcp4/tests/dhcp4_test_utils.h>
|
#include <dhcp4/tests/dhcp4_test_utils.h>
|
||||||
#include <util/optional_value.h>
|
#include <util/optional_value.h>
|
||||||
@@ -73,6 +74,8 @@ public:
|
|||||||
Option4AddrLst::AddressContainer log_servers_;
|
Option4AddrLst::AddressContainer log_servers_;
|
||||||
/// @brief Holds IP addresses received in the Quotes Servers option.
|
/// @brief Holds IP addresses received in the Quotes Servers option.
|
||||||
Option4AddrLst::AddressContainer quotes_servers_;
|
Option4AddrLst::AddressContainer quotes_servers_;
|
||||||
|
/// @brief Vendor Specific options
|
||||||
|
OptionCollection vendor_suboptions_;
|
||||||
/// @brief Holds a lease obtained by the client.
|
/// @brief Holds a lease obtained by the client.
|
||||||
Lease4 lease_;
|
Lease4 lease_;
|
||||||
/// @brief Holds server id of the server which responded to the client's
|
/// @brief Holds server id of the server which responded to the client's
|
||||||
|
555
src/bin/dhcp4/tests/host_options_unittest.cc
Normal file
555
src/bin/dhcp4/tests/host_options_unittest.cc
Normal file
@@ -0,0 +1,555 @@
|
|||||||
|
// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <asiolink/io_address.h>
|
||||||
|
#include <dhcp/dhcp4.h>
|
||||||
|
#include <dhcp/docsis3_option_defs.h>
|
||||||
|
#include <dhcp/option_int.h>
|
||||||
|
#include <dhcp/option_vendor.h>
|
||||||
|
#include <dhcp/tests/iface_mgr_test_config.h>
|
||||||
|
#include <dhcp4/tests/dhcp4_test_utils.h>
|
||||||
|
#include <dhcp4/tests/dhcp4_client.h>
|
||||||
|
#include <stats/stats_mgr.h>
|
||||||
|
|
||||||
|
using namespace isc;
|
||||||
|
using namespace isc::asiolink;
|
||||||
|
using namespace isc::dhcp;
|
||||||
|
using namespace isc::dhcp::test;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/// @brief Boolean value used to signal stateless configuration test.
|
||||||
|
const bool STATELESS = true;
|
||||||
|
|
||||||
|
/// @brief Boolean value used to signal stateful configuration test.
|
||||||
|
const bool STATEFUL = false;
|
||||||
|
|
||||||
|
/// @brief Set of JSON configurations used throughout the tests.
|
||||||
|
///
|
||||||
|
/// - Configuration 0:
|
||||||
|
/// - Used to test that host specific options override subnet specific
|
||||||
|
/// options when these options are requested with PRL option.
|
||||||
|
/// - Single subnet 10.0.0.0/24 with a pool of 10.0.0.10-10.0.0.100
|
||||||
|
/// - 4 options configured within subnet scope
|
||||||
|
/// - routers: 10.0.0.200,10.0.0.201,
|
||||||
|
/// - domain-name-servers: 10.0.0.202,10.0.0.203,
|
||||||
|
/// - log-servers: 10.0.0.200,10.0.0.201,
|
||||||
|
/// - cookie-servers: 10.0.0.202,10.0.0.203
|
||||||
|
/// - Single reservation within the subnet:
|
||||||
|
/// - HW address: aa:bb:cc:dd:ee:ff
|
||||||
|
/// - ip-address: 10.0.0.7
|
||||||
|
/// - Two options overriding subnet specific options:
|
||||||
|
/// - cookie-servers: 10.1.1.202, 10.1.1.203
|
||||||
|
/// - log-servers: 10.1.1.200, 10.1.1.201
|
||||||
|
///
|
||||||
|
/// - Configuration 1:
|
||||||
|
/// - Used to test that host specific options override subnet specific
|
||||||
|
/// default options. Default options are those that are sent even when
|
||||||
|
/// not requested by a client.
|
||||||
|
/// - Single subnet 10.0.0.0/24 with a pool of 10.0.0.10-10.0.0.100
|
||||||
|
/// - 4 options configured within subnet scope
|
||||||
|
/// - routers: 10.0.0.200,10.0.0.201,
|
||||||
|
/// - domain-name-servers: 10.0.0.202,10.0.0.203,
|
||||||
|
/// - log-servers: 10.0.0.200,10.0.0.201,
|
||||||
|
/// - cookie-servers: 10.0.0.202,10.0.0.203
|
||||||
|
/// - Single reservation within the subnet:
|
||||||
|
/// - HW address: aa:bb:cc:dd:ee:ff
|
||||||
|
/// - ip-address: 10.0.0.7
|
||||||
|
/// - Two options overriding subnet specific default options:
|
||||||
|
/// - routers: 10.1.1.200, 10.1.1.201
|
||||||
|
/// - domain-name-servers: 10.1.1.202, 10.1.1.203
|
||||||
|
///
|
||||||
|
/// - Configuration 2:
|
||||||
|
/// - Used to test that client receives options solely specified in a
|
||||||
|
/// host scope.
|
||||||
|
/// - Single reservation within the subnet:
|
||||||
|
/// - HW address: aa:bb:cc:dd:ee:ff
|
||||||
|
/// - ip-address: 10.0.0.7
|
||||||
|
/// - Two options:
|
||||||
|
/// - routers: 10.1.1.200, 10.1.1.201
|
||||||
|
/// - cookie-servers: 10.1.1.202, 10.1.1.203
|
||||||
|
///
|
||||||
|
/// - Configuration 3:
|
||||||
|
/// - Used to test that host specific vendor options override globally
|
||||||
|
/// specified vendor options.
|
||||||
|
/// - Globally specified option 125 with Cable Labs vendor id.
|
||||||
|
/// - TFTP servers sub option: 10.0.0.202,10.0.0.203
|
||||||
|
/// - Single subnet 10.0.0.0/24 with a pool of 10.0.0.10-10.0.0.100
|
||||||
|
/// - Single reservation within the subnet:
|
||||||
|
/// - HW address: aa:bb:cc:dd:ee:ff
|
||||||
|
/// - ip-adress 10.0.0.7
|
||||||
|
/// - Vendor option for Cable Labs vendor id specified for the reservation:
|
||||||
|
/// - TFTP servers suboption overriding globally spececified suboption:
|
||||||
|
/// 10.1.1.202,10.1.1.203
|
||||||
|
///
|
||||||
|
const char* HOST_CONFIGS[] = {
|
||||||
|
// Configuration 0
|
||||||
|
"{ \"interfaces-config\": {"
|
||||||
|
" \"interfaces\": [ \"*\" ]"
|
||||||
|
"},"
|
||||||
|
"\"valid-lifetime\": 600,"
|
||||||
|
"\"subnet4\": [ { "
|
||||||
|
" \"subnet\": \"10.0.0.0/24\", "
|
||||||
|
" \"id\": 1,"
|
||||||
|
" \"relay\": { \"ip-address\": \"10.0.0.233\" },"
|
||||||
|
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
|
||||||
|
" \"option-data\": [ {"
|
||||||
|
" \"name\": \"routers\","
|
||||||
|
" \"data\": \"10.0.0.200,10.0.0.201\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"domain-name-servers\","
|
||||||
|
" \"data\": \"10.0.0.202,10.0.0.203\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"log-servers\","
|
||||||
|
" \"data\": \"10.0.0.204,10.0.0.205\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"cookie-servers\","
|
||||||
|
" \"data\": \"10.0.0.206,10.0.0.207\""
|
||||||
|
" } ],"
|
||||||
|
" \"reservations\": [ "
|
||||||
|
" {"
|
||||||
|
" \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
|
||||||
|
" \"ip-address\": \"10.0.0.7\","
|
||||||
|
" \"option-data\": [ {"
|
||||||
|
" \"name\": \"cookie-servers\","
|
||||||
|
" \"data\": \"10.1.1.202,10.1.1.203\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"log-servers\","
|
||||||
|
" \"data\": \"10.1.1.200,10.1.1.201\""
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
"}",
|
||||||
|
|
||||||
|
// Configuration 1
|
||||||
|
"{ \"interfaces-config\": {"
|
||||||
|
" \"interfaces\": [ \"*\" ]"
|
||||||
|
"},"
|
||||||
|
"\"valid-lifetime\": 600,"
|
||||||
|
"\"subnet4\": [ { "
|
||||||
|
" \"subnet\": \"10.0.0.0/24\", "
|
||||||
|
" \"id\": 1,"
|
||||||
|
" \"relay\": { \"ip-address\": \"10.0.0.233\" },"
|
||||||
|
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
|
||||||
|
" \"option-data\": [ {"
|
||||||
|
" \"name\": \"routers\","
|
||||||
|
" \"data\": \"10.0.0.200,10.0.0.201\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"domain-name-servers\","
|
||||||
|
" \"data\": \"10.0.0.202,10.0.0.203\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"log-servers\","
|
||||||
|
" \"data\": \"10.0.0.204,10.0.0.205\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"cookie-servers\","
|
||||||
|
" \"data\": \"10.0.0.206,10.0.0.207\""
|
||||||
|
" } ],"
|
||||||
|
" \"reservations\": [ "
|
||||||
|
" {"
|
||||||
|
" \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
|
||||||
|
" \"ip-address\": \"10.0.0.7\","
|
||||||
|
" \"option-data\": [ {"
|
||||||
|
" \"name\": \"routers\","
|
||||||
|
" \"data\": \"10.1.1.200,10.1.1.201\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"domain-name-servers\","
|
||||||
|
" \"data\": \"10.1.1.202,10.1.1.203\""
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
"}",
|
||||||
|
|
||||||
|
// Configuration 2
|
||||||
|
"{ \"interfaces-config\": {"
|
||||||
|
" \"interfaces\": [ \"*\" ]"
|
||||||
|
"},"
|
||||||
|
"\"valid-lifetime\": 600,"
|
||||||
|
"\"subnet4\": [ { "
|
||||||
|
" \"subnet\": \"10.0.0.0/24\", "
|
||||||
|
" \"id\": 1,"
|
||||||
|
" \"relay\": { \"ip-address\": \"10.0.0.233\" },"
|
||||||
|
" \"reservations\": [ "
|
||||||
|
" {"
|
||||||
|
" \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
|
||||||
|
" \"ip-address\": \"10.0.0.7\","
|
||||||
|
" \"option-data\": [ {"
|
||||||
|
" \"name\": \"routers\","
|
||||||
|
" \"data\": \"10.1.1.200,10.1.1.201\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"cookie-servers\","
|
||||||
|
" \"data\": \"10.1.1.206,10.1.1.207\""
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
"}",
|
||||||
|
|
||||||
|
// Configuration 3
|
||||||
|
"{ \"interfaces-config\": {"
|
||||||
|
" \"interfaces\": [ \"*\" ]"
|
||||||
|
"},"
|
||||||
|
"\"valid-lifetime\": 600,"
|
||||||
|
"\"option-data\": [ {"
|
||||||
|
" \"name\": \"vivso-suboptions\","
|
||||||
|
" \"data\": 4491"
|
||||||
|
"},"
|
||||||
|
"{"
|
||||||
|
" \"name\": \"tftp-servers\","
|
||||||
|
" \"space\": \"vendor-4491\","
|
||||||
|
" \"data\": \"10.0.0.202,10.0.0.203\""
|
||||||
|
"} ],"
|
||||||
|
"\"subnet4\": [ { "
|
||||||
|
" \"subnet\": \"10.0.0.0/24\", "
|
||||||
|
" \"id\": 1,"
|
||||||
|
" \"relay\": { \"ip-address\": \"10.0.0.233\" },"
|
||||||
|
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
|
||||||
|
" \"reservations\": [ "
|
||||||
|
" {"
|
||||||
|
" \"hw-address\": \"aa:bb:cc:dd:ee:ff\","
|
||||||
|
" \"ip-address\": \"10.0.0.7\","
|
||||||
|
" \"option-data\": [ {"
|
||||||
|
" \"name\": \"vivso-suboptions\","
|
||||||
|
" \"data\": 4491"
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"name\": \"tftp-servers\","
|
||||||
|
" \"space\": \"vendor-4491\","
|
||||||
|
" \"data\": \"10.1.1.202,10.1.1.203\""
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
" } ]"
|
||||||
|
"}"
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Test fixture class for testing static reservations of options.
|
||||||
|
class HostOptionsTest : public Dhcpv4SrvTest {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Constructor.
|
||||||
|
///
|
||||||
|
/// Sets up fake interfaces.
|
||||||
|
HostOptionsTest()
|
||||||
|
: Dhcpv4SrvTest(),
|
||||||
|
iface_mgr_test_config_(true) {
|
||||||
|
IfaceMgr::instance().openSockets4();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Verifies that host specific options override subnet specific
|
||||||
|
/// options.
|
||||||
|
///
|
||||||
|
/// Overridden options are requested with Parameter Request List
|
||||||
|
/// option.
|
||||||
|
///
|
||||||
|
/// @param stateless Boolean value indicating if statless or stateful
|
||||||
|
/// configuration should be performed.
|
||||||
|
void testOverrideRequestedOptions(const bool stateless);
|
||||||
|
|
||||||
|
/// @brief Verifies that host specific options override subnet specific
|
||||||
|
/// options.
|
||||||
|
///
|
||||||
|
/// Overridden options are the options which server sends regardless
|
||||||
|
/// if they are requested with Parameter Request List option or not.
|
||||||
|
///
|
||||||
|
/// @param stateless Boolean value indicating if statless or stateful
|
||||||
|
/// configuration should be performed.
|
||||||
|
void testOverrideDefaultOptions(const bool stateless);
|
||||||
|
|
||||||
|
/// @brief Verifies that client receives options when they are solely
|
||||||
|
/// defined in the host scope (and not in the global or subnet scope).
|
||||||
|
///
|
||||||
|
/// @param stateless Boolean value indicating if statless or stateful
|
||||||
|
/// configuration should be performed.
|
||||||
|
void testHostOnlyOptions(const bool stateless);
|
||||||
|
|
||||||
|
/// @brief Verifies that host specific vendor options override vendor
|
||||||
|
/// options defined in the global scope.
|
||||||
|
///
|
||||||
|
/// @param stateless Boolean value indicating if statless or stateful
|
||||||
|
/// configuration should be performed.
|
||||||
|
void testOverrideVendorOptions(const bool stateless);
|
||||||
|
|
||||||
|
/// @brief Interface Manager's fake configuration control.
|
||||||
|
IfaceMgrTestConfig iface_mgr_test_config_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
HostOptionsTest::testOverrideRequestedOptions(const bool stateless) {
|
||||||
|
Dhcp4Client client(Dhcp4Client::SELECTING);
|
||||||
|
client.setHWAddress("aa:bb:cc:dd:ee:ff");
|
||||||
|
client.requestOptions(DHO_DOMAIN_NAME_SERVERS, DHO_LOG_SERVERS,
|
||||||
|
DHO_COOKIE_SERVERS);
|
||||||
|
|
||||||
|
// Configure DHCP server.
|
||||||
|
configure(HOST_CONFIGS[0], *client.getServer());
|
||||||
|
|
||||||
|
if (stateless) {
|
||||||
|
// Need to relay the message from a specific address which can
|
||||||
|
// be matched with a configured subnet.
|
||||||
|
client.useRelay(true, IOAddress("10.0.0.233"));
|
||||||
|
ASSERT_NO_THROW(client.doInform());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Perform 4-way exchange with the server but to not request any
|
||||||
|
// specific address in the DHCPDISCOVER message.
|
||||||
|
ASSERT_NO_THROW(client.doDORA());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the server responded.
|
||||||
|
ASSERT_TRUE(client.getContext().response_);
|
||||||
|
Pkt4Ptr resp = client.getContext().response_;
|
||||||
|
// Make sure that the server has responded with DHCPACK.
|
||||||
|
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||||
|
|
||||||
|
if (!stateless) {
|
||||||
|
// Make sure that the client has got the lease for the reserved
|
||||||
|
// address.
|
||||||
|
ASSERT_EQ("10.0.0.7", client.config_.lease_.addr_.toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ(2, client.config_.routers_.size());
|
||||||
|
EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
|
||||||
|
EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
|
||||||
|
// Make sure that the DNS Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.dns_servers_.size());
|
||||||
|
EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
|
||||||
|
// Make sure that the Quotes Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
||||||
|
EXPECT_EQ("10.1.1.202", client.config_.quotes_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.203", client.config_.quotes_servers_[1].toText());
|
||||||
|
// Make sure that the Log Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.log_servers_.size());
|
||||||
|
EXPECT_EQ("10.1.1.200", client.config_.log_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.201", client.config_.log_servers_[1].toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HostOptionsTest::testOverrideDefaultOptions(const bool stateless) {
|
||||||
|
Dhcp4Client client(Dhcp4Client::SELECTING);
|
||||||
|
client.setHWAddress("aa:bb:cc:dd:ee:ff");
|
||||||
|
|
||||||
|
client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
|
||||||
|
|
||||||
|
// Configure DHCP server.
|
||||||
|
configure(HOST_CONFIGS[1], *client.getServer());
|
||||||
|
|
||||||
|
if (stateless) {
|
||||||
|
// Need to relay the message from a specific address which can
|
||||||
|
// be matched with a configured subnet.
|
||||||
|
client.useRelay(true, IOAddress("10.0.0.233"));
|
||||||
|
ASSERT_NO_THROW(client.doInform());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Perform 4-way exchange with the server but to not request any
|
||||||
|
// specific address in the DHCPDISCOVER message.
|
||||||
|
ASSERT_NO_THROW(client.doDORA());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform 4-way exchange with the server but to not request any
|
||||||
|
// specific address in the DHCPDISCOVER message.
|
||||||
|
ASSERT_NO_THROW(client.doDORA());
|
||||||
|
|
||||||
|
// Make sure that the server responded.
|
||||||
|
ASSERT_TRUE(client.getContext().response_);
|
||||||
|
Pkt4Ptr resp = client.getContext().response_;
|
||||||
|
// Make sure that the server has responded with DHCPACK.
|
||||||
|
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||||
|
|
||||||
|
if (!stateless) {
|
||||||
|
// Make sure that the client has got the lease for the reserved
|
||||||
|
// address.
|
||||||
|
ASSERT_EQ("10.0.0.7", client.config_.lease_.addr_.toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_EQ(2, client.config_.routers_.size());
|
||||||
|
EXPECT_EQ("10.1.1.200", client.config_.routers_[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.201", client.config_.routers_[1].toText());
|
||||||
|
// Make sure that the DNS Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.dns_servers_.size());
|
||||||
|
EXPECT_EQ("10.1.1.202", client.config_.dns_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.203", client.config_.dns_servers_[1].toText());
|
||||||
|
// Make sure that the Quotes Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
||||||
|
EXPECT_EQ("10.0.0.206", client.config_.quotes_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.0.0.207", client.config_.quotes_servers_[1].toText());
|
||||||
|
// Make sure that the Log Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.log_servers_.size());
|
||||||
|
EXPECT_EQ("10.0.0.204", client.config_.log_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.0.0.205", client.config_.log_servers_[1].toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HostOptionsTest::testHostOnlyOptions(const bool stateless) {
|
||||||
|
Dhcp4Client client(Dhcp4Client::SELECTING);
|
||||||
|
client.setHWAddress("aa:bb:cc:dd:ee:ff");
|
||||||
|
client.requestOptions(DHO_COOKIE_SERVERS);
|
||||||
|
|
||||||
|
// Configure DHCP server.
|
||||||
|
configure(HOST_CONFIGS[2], *client.getServer());
|
||||||
|
|
||||||
|
if (stateless) {
|
||||||
|
// Need to relay the message from a specific address which can
|
||||||
|
// be matched with a configured subnet.
|
||||||
|
client.useRelay(true, IOAddress("10.0.0.233"));
|
||||||
|
ASSERT_NO_THROW(client.doInform());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Perform 4-way exchange with the server but to not request any
|
||||||
|
// specific address in the DHCPDISCOVER message.
|
||||||
|
ASSERT_NO_THROW(client.doDORA());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the server responded.
|
||||||
|
ASSERT_TRUE(client.getContext().response_);
|
||||||
|
Pkt4Ptr resp = client.getContext().response_;
|
||||||
|
// Make sure that the server has responded with DHCPACK.
|
||||||
|
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||||
|
|
||||||
|
if (!stateless) {
|
||||||
|
// Make sure that the client has got the lease for the reserved
|
||||||
|
// address.
|
||||||
|
ASSERT_EQ("10.0.0.7", client.config_.lease_.addr_.toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the Routers options has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.routers_.size());
|
||||||
|
EXPECT_EQ("10.1.1.200", client.config_.routers_[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.201", client.config_.routers_[1].toText());
|
||||||
|
// Make sure that the Quotes Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
||||||
|
EXPECT_EQ("10.1.1.206", client.config_.quotes_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.207", client.config_.quotes_servers_[1].toText());
|
||||||
|
|
||||||
|
// Other options are not configured and should not be delivered.
|
||||||
|
EXPECT_EQ(0, client.config_.dns_servers_.size());
|
||||||
|
EXPECT_EQ(0, client.config_.log_servers_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HostOptionsTest::testOverrideVendorOptions(const bool stateless) {
|
||||||
|
Dhcp4Client client(Dhcp4Client::SELECTING);
|
||||||
|
client.setHWAddress("aa:bb:cc:dd:ee:ff");
|
||||||
|
|
||||||
|
// Client needs to include V-I Vendor Specific Information option
|
||||||
|
// to include ORO suboption, which the server will use to determine
|
||||||
|
// which suboptions should be returned to the client.
|
||||||
|
OptionVendorPtr opt_vendor(new OptionVendor(Option::V4,
|
||||||
|
VENDOR_ID_CABLE_LABS));
|
||||||
|
// Include ORO with TFTP servers suboption code being requested.
|
||||||
|
opt_vendor->addOption(OptionPtr(new OptionUint8(Option::V4, DOCSIS3_V4_ORO,
|
||||||
|
DOCSIS3_V4_TFTP_SERVERS)));
|
||||||
|
client.addExtraOption(opt_vendor);
|
||||||
|
|
||||||
|
// Configure DHCP server.
|
||||||
|
configure(HOST_CONFIGS[3], *client.getServer());
|
||||||
|
|
||||||
|
if (stateless) {
|
||||||
|
// Need to relay the message from a specific address which can
|
||||||
|
// be matched with a configured subnet.
|
||||||
|
client.useRelay(true, IOAddress("10.0.0.233"));
|
||||||
|
ASSERT_NO_THROW(client.doInform());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Perform 4-way exchange with the server.
|
||||||
|
ASSERT_NO_THROW(client.doDORA());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that the server responded.
|
||||||
|
ASSERT_TRUE(client.getContext().response_);
|
||||||
|
Pkt4Ptr resp = client.getContext().response_;
|
||||||
|
// Make sure that the server has responded with DHCPACK.
|
||||||
|
ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
|
||||||
|
|
||||||
|
if (!stateless) {
|
||||||
|
// Make sure that the client has got the lease for the reserved
|
||||||
|
// address.
|
||||||
|
ASSERT_EQ("10.0.0.7", client.config_.lease_.addr_.toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the server has responded with a V-I Vendor Specific
|
||||||
|
// Information option with exactly one suboption.
|
||||||
|
ASSERT_EQ(1, client.config_.vendor_suboptions_.size());
|
||||||
|
// Assume this suboption is a TFTP servers suboption.
|
||||||
|
std::multimap<unsigned int, OptionPtr>::const_iterator opt =
|
||||||
|
client.config_.vendor_suboptions_.find(DOCSIS3_V4_TFTP_SERVERS);
|
||||||
|
ASSERT_TRUE(opt->second);
|
||||||
|
Option4AddrLstPtr opt_tftp = boost::dynamic_pointer_cast<
|
||||||
|
Option4AddrLst>(opt->second);
|
||||||
|
ASSERT_TRUE(opt_tftp);
|
||||||
|
// TFTP servers suboption should contain addresses specified on host level.
|
||||||
|
const Option4AddrLst::AddressContainer& tftps = opt_tftp->getAddresses();
|
||||||
|
ASSERT_EQ(2, tftps.size());
|
||||||
|
EXPECT_EQ("10.1.1.202", tftps[0].toText());
|
||||||
|
EXPECT_EQ("10.1.1.203", tftps[1].toText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that host specific options override subnet specific
|
||||||
|
// options. Overridden options are requested with Parameter Request List
|
||||||
|
// option (stateless case).
|
||||||
|
TEST_F(HostOptionsTest, overrideRequestedOptionsStateless) {
|
||||||
|
testOverrideRequestedOptions(STATELESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that host specific options override subnet specific
|
||||||
|
// options. Overridden options are requested with Parameter Request List
|
||||||
|
// option (stateful case).
|
||||||
|
TEST_F(HostOptionsTest, overrideRequestedOptionsStateful) {
|
||||||
|
testOverrideRequestedOptions(STATEFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that host specific options override subnet specific
|
||||||
|
// options. Overridden options are the options which server sends
|
||||||
|
// regardless if they are requested with Parameter Request List option
|
||||||
|
// or not (stateless case).
|
||||||
|
TEST_F(HostOptionsTest, overrideDefaultOptionsStateless) {
|
||||||
|
testOverrideDefaultOptions(STATELESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that host specific options override subnet specific
|
||||||
|
// options. Overridden options are the options which server sends
|
||||||
|
// regardless if they are requested with Parameter Request List option
|
||||||
|
// or not (stateful case).
|
||||||
|
TEST_F(HostOptionsTest, overrideDefaultOptionsStateful) {
|
||||||
|
testOverrideDefaultOptions(STATEFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that client receives options when they are
|
||||||
|
// solely defined in the host scope and not in the global or subnet
|
||||||
|
// scope (stateless case).
|
||||||
|
TEST_F(HostOptionsTest, hostOnlyOptionsStateless) {
|
||||||
|
testHostOnlyOptions(STATELESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that client receives options when they are
|
||||||
|
// solely defined in the host scope and not in the global or subnet
|
||||||
|
// scope (stateful case).
|
||||||
|
TEST_F(HostOptionsTest, hostOnlyOptionsStateful) {
|
||||||
|
testHostOnlyOptions(STATEFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that host specific vendor options override vendor
|
||||||
|
// options defined in the global scope (stateless case).
|
||||||
|
TEST_F(HostOptionsTest, overrideVendorOptionsStateless) {
|
||||||
|
testOverrideVendorOptions(STATELESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test checks that host specific vendor options override vendor
|
||||||
|
// options defined in the global scope (stateful case).
|
||||||
|
TEST_F(HostOptionsTest, overrideVendorOptionsStateful) {
|
||||||
|
testOverrideVendorOptions(STATEFUL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -58,11 +58,11 @@ const char* INFORM_CONFIGS[] = {
|
|||||||
" },"
|
" },"
|
||||||
" {"
|
" {"
|
||||||
" \"name\": \"log-servers\","
|
" \"name\": \"log-servers\","
|
||||||
" \"data\": \"10.0.0.200,10.0.0.201\""
|
" \"data\": \"10.0.0.202,10.0.0.203\""
|
||||||
" },"
|
" },"
|
||||||
" {"
|
" {"
|
||||||
" \"name\": \"cookie-servers\","
|
" \"name\": \"cookie-servers\","
|
||||||
" \"data\": \"10.0.0.202,10.0.0.203\""
|
" \"data\": \"10.0.0.200,10.0.0.201\""
|
||||||
" } ]"
|
" } ]"
|
||||||
" } ]"
|
" } ]"
|
||||||
"}",
|
"}",
|
||||||
@@ -159,12 +159,12 @@ TEST_F(InformTest, directClientBroadcast) {
|
|||||||
EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
|
EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
|
||||||
// Make sure that the Log Servers option has been received.
|
// Make sure that the Log Servers option has been received.
|
||||||
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
||||||
EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
|
EXPECT_EQ("10.0.0.200", client.config_.quotes_servers_[0].toText());
|
||||||
EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
|
EXPECT_EQ("10.0.0.201", client.config_.quotes_servers_[1].toText());
|
||||||
// Make sure that the Quotes Servers option has been received.
|
// Make sure that the Quotes Servers option has been received.
|
||||||
ASSERT_EQ(2, client.config_.log_servers_.size());
|
ASSERT_EQ(2, client.config_.log_servers_.size());
|
||||||
EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
|
EXPECT_EQ("10.0.0.202", client.config_.log_servers_[0].toText());
|
||||||
EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
|
EXPECT_EQ("10.0.0.203", client.config_.log_servers_[1].toText());
|
||||||
|
|
||||||
// Check that we can send another DHCPINFORM message using
|
// Check that we can send another DHCPINFORM message using
|
||||||
// different ciaddr and we will get the configuration.
|
// different ciaddr and we will get the configuration.
|
||||||
@@ -313,14 +313,14 @@ TEST_F(InformTest, relayedClient) {
|
|||||||
ASSERT_EQ(2, client.config_.dns_servers_.size());
|
ASSERT_EQ(2, client.config_.dns_servers_.size());
|
||||||
EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
|
EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
|
||||||
EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
|
EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
|
||||||
// Make sure that the Log Servers option has been received.
|
|
||||||
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
|
||||||
EXPECT_EQ("192.0.2.200", client.config_.routers_[0].toText());
|
|
||||||
EXPECT_EQ("192.0.2.201", client.config_.routers_[1].toText());
|
|
||||||
// Make sure that the Quotes Servers option has been received.
|
// Make sure that the Quotes Servers option has been received.
|
||||||
|
ASSERT_EQ(2, client.config_.quotes_servers_.size());
|
||||||
|
EXPECT_EQ("10.0.0.202", client.config_.quotes_servers_[0].toText());
|
||||||
|
EXPECT_EQ("10.0.0.203", client.config_.quotes_servers_[1].toText());
|
||||||
|
// Make sure that the Log Servers option has been received.
|
||||||
ASSERT_EQ(2, client.config_.log_servers_.size());
|
ASSERT_EQ(2, client.config_.log_servers_.size());
|
||||||
EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
|
EXPECT_EQ("10.0.0.200", client.config_.log_servers_[0].toText());
|
||||||
EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
|
EXPECT_EQ("10.0.0.201", client.config_.log_servers_[1].toText());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test checks that the server can respond to the DHCPINFORM message
|
// This test checks that the server can respond to the DHCPINFORM message
|
||||||
|
@@ -211,7 +211,19 @@ const OptionDefParams OPTION_DEF_PARAMS4[] = {
|
|||||||
{ "domain-search", DHO_DOMAIN_SEARCH, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
|
{ "domain-search", DHO_DOMAIN_SEARCH, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
|
||||||
{ "vivco-suboptions", DHO_VIVCO_SUBOPTIONS, OPT_RECORD_TYPE,
|
{ "vivco-suboptions", DHO_VIVCO_SUBOPTIONS, OPT_RECORD_TYPE,
|
||||||
false, RECORD_DEF(VIVCO_RECORDS), "" },
|
false, RECORD_DEF(VIVCO_RECORDS), "" },
|
||||||
{ "vivso-suboptions", DHO_VIVSO_SUBOPTIONS, OPT_BINARY_TYPE,
|
// Vendor-Identifying Vendor Specific Information option payload begins with a
|
||||||
|
// 32-bit log enterprise number, followed by a tuple of data-len/option-data.
|
||||||
|
// The format defined here includes 32-bit field holding enterprise number.
|
||||||
|
// This allows for specifying option-data information where the enterprise-id
|
||||||
|
// is represented by a uint32_t value. Previously we represented this option
|
||||||
|
// as a binary, but that would imply that enterprise number would have to be
|
||||||
|
// represented in binary format in the server configuration. That would be
|
||||||
|
// inconvenient and non-intuitive.
|
||||||
|
/// @todo We need to extend support for vendor options with ability to specify
|
||||||
|
/// multiple enterprise numbers for a single option. Perhaps it would be
|
||||||
|
/// ok to specify multiple instances of the "vivso-suboptions" which will be
|
||||||
|
/// combined in a single option by the server before responding to a client.
|
||||||
|
{ "vivso-suboptions", DHO_VIVSO_SUBOPTIONS, OPT_UINT32_TYPE,
|
||||||
false, NO_RECORD_DEF, "" }
|
false, NO_RECORD_DEF, "" }
|
||||||
|
|
||||||
// @todo add definitions for all remaning options.
|
// @todo add definitions for all remaning options.
|
||||||
|
Reference in New Issue
Block a user