Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
c29551e4
Commit
c29551e4
authored
Jun 14, 2016
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac3573'
parents
e7324065
774b4fa4
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp6/dhcp6_srv.cc
View file @
c29551e4
...
...
@@ -794,7 +794,12 @@ void
Dhcpv6Srv
::
buildCfgOptionList
(
const
Pkt6Ptr
&
question
,
AllocEngine
::
ClientContext6
&
ctx
,
CfgOptionList
&
co_list
)
{
// First subnet configured options
// Firstly, host specific options.
if
(
ctx
.
host_
&&
!
ctx
.
host_
->
getCfgOption6
()
->
empty
())
{
co_list
.
push_back
(
ctx
.
host_
->
getCfgOption6
());
}
// Next, subnet configured options.
if
(
ctx
.
subnet_
&&
!
ctx
.
subnet_
->
getCfgOption
()
->
empty
())
{
co_list
.
push_back
(
ctx
.
subnet_
->
getCfgOption
());
}
...
...
src/bin/dhcp6/tests/dhcp6_client.cc
View file @
c29551e4
...
...
@@ -469,6 +469,11 @@ Dhcp6Client::doInfRequest() {
sendMsg
(
context_
.
query_
);
context_
.
response_
=
receiveOneMsg
();
// Apply new configuration only if the server has responded.
if
(
context_
.
response_
)
{
config_
.
clear
();
applyRcvdConfiguration
(
context_
.
response_
);
}
}
void
...
...
src/bin/dhcp6/tests/host_unittest.cc
View file @
c29551e4
...
...
@@ -6,6 +6,10 @@
#include
<config.h>
#include
<asiolink/io_address.h>
#include
<dhcp/docsis3_option_defs.h>
#include
<dhcp/option6_addrlst.h>
#include
<dhcp/option_int.h>
#include
<dhcp/option_vendor.h>
#include
<dhcp/tests/iface_mgr_test_config.h>
#include
<dhcp6/tests/dhcp6_test_utils.h>
#include
<dhcp6/tests/dhcp6_client.h>
...
...
@@ -21,11 +25,25 @@ namespace {
///
/// - Configuration 0:
/// Single subnet with two reservations, one with a hostname, one without
///
/// - Configuration 1:
/// Multiple reservations using different host identifiers.
///
/// - Configuration 2:
/// Same as configuration 1 but 'host-reservation-identifiers' specified
/// in non-default order.
///
/// - Configuration 3:
/// - Used to test that host specific options override subnet specific
/// options and global options.
///
/// - Configuration 4:
/// - Used to test that client receives options solely specified in a
/// host scope.
///
/// - Configuration 5:
/// - Used to test that host specific vendor options override globally
/// specified vendor options.
const
char
*
CONFIGS
[]
=
{
// Configuration 0:
"{ "
...
...
@@ -107,7 +125,127 @@ const char* CONFIGS[] = {
"
\"
ip-addresses
\"
: [
\"
2001:db8:1::2
\"
]"
" } ]"
" } ]"
"}"
,
// Configuration 3:
"{ "
"
\"
interfaces-config
\"
: {"
"
\"
interfaces
\"
: [
\"
*
\"
]"
"},"
"
\"
host-reservation-identifiers
\"
: [
\"
duid
\"
],"
"
\"
valid-lifetime
\"
: 4000, "
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
nisp-servers
\"
,"
"
\"
data
\"
:
\"
3000:3::123
\"
"
"} ],"
"
\"
subnet6
\"
: [ "
" { "
"
\"
subnet
\"
:
\"
2001:db8:1::/48
\"
, "
"
\"
pools
\"
: [ {
\"
pool
\"
:
\"
2001:db8:1::/64
\"
} ],"
"
\"
interface
\"
:
\"
eth0
\"
,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
dns-servers
\"
,"
"
\"
data
\"
:
\"
3000:2::123
\"
"
" },"
" {"
"
\"
name
\"
:
\"
nis-servers
\"
,"
"
\"
data
\"
:
\"
3000:2::123
\"
"
" },"
" {"
"
\"
name
\"
:
\"
sntp-servers
\"
,"
"
\"
data
\"
:
\"
3000:2::123
\"
"
" } ],"
"
\"
reservations
\"
: ["
" {"
"
\"
duid
\"
:
\"
01:02:03:05
\"
,"
"
\"
ip-addresses
\"
: [
\"
2001:db8:1::2
\"
],"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
dns-servers
\"
,"
"
\"
data
\"
:
\"
3000:1::234
\"
"
" },"
" {"
"
\"
name
\"
:
\"
nis-servers
\"
,"
"
\"
data
\"
:
\"
3000:1::234
\"
"
" } ]"
" } ]"
" } ]"
"}"
,
// Configuration 4:
"{ "
"
\"
interfaces-config
\"
: {"
"
\"
interfaces
\"
: [
\"
*
\"
]"
"},"
"
\"
host-reservation-identifiers
\"
: [
\"
duid
\"
],"
"
\"
valid-lifetime
\"
: 4000, "
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
subnet6
\"
: [ "
" { "
"
\"
subnet
\"
:
\"
2001:db8:1::/48
\"
, "
"
\"
pools
\"
: [ {
\"
pool
\"
:
\"
2001:db8:1::/64
\"
} ],"
"
\"
interface
\"
:
\"
eth0
\"
,"
"
\"
reservations
\"
: ["
" {"
"
\"
duid
\"
:
\"
01:02:03:05
\"
,"
"
\"
ip-addresses
\"
: [
\"
2001:db8:1::2
\"
],"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
dns-servers
\"
,"
"
\"
data
\"
:
\"
3000:1::234
\"
"
" },"
" {"
"
\"
name
\"
:
\"
nis-servers
\"
,"
"
\"
data
\"
:
\"
3000:1::234
\"
"
" } ]"
" } ]"
" } ]"
"}"
,
// Configuration 5:
"{ "
"
\"
interfaces-config
\"
: {"
"
\"
interfaces
\"
: [
\"
*
\"
]"
"},"
"
\"
host-reservation-identifiers
\"
: [
\"
duid
\"
],"
"
\"
valid-lifetime
\"
: 4000, "
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
vendor-opts
\"
,"
"
\"
data
\"
: 4491"
"},"
"{"
"
\"
name
\"
:
\"
tftp-servers
\"
,"
"
\"
space
\"
:
\"
vendor-4491
\"
,"
"
\"
data
\"
:
\"
3000:3::123
\"
"
"} ],"
"
\"
subnet6
\"
: [ "
" { "
"
\"
subnet
\"
:
\"
2001:db8:1::/48
\"
, "
"
\"
pools
\"
: [ {
\"
pool
\"
:
\"
2001:db8:1::/64
\"
} ],"
"
\"
interface
\"
:
\"
eth0
\"
,"
"
\"
reservations
\"
: ["
" {"
"
\"
duid
\"
:
\"
01:02:03:05
\"
,"
"
\"
ip-addresses
\"
: [
\"
2001:db8:1::2
\"
],"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
vendor-opts
\"
,"
"
\"
data
\"
: 4491"
" },"
" {"
"
\"
name
\"
:
\"
tftp-servers
\"
,"
"
\"
space
\"
:
\"
vendor-4491
\"
,"
"
\"
data
\"
:
\"
3000:1::234
\"
"
" } ]"
" } ]"
" } ]"
"}"
};
/// @brief Test fixture class for testing host reservations
...
...
@@ -121,6 +259,28 @@ public:
iface_mgr_test_config_
(
true
)
{
}
/// @brief Checks that specified option contains a desired address.
///
/// The option must cast to the @ref Option6AddrLst type. The function
/// expects that this option contains at least one address and checks
/// first address for equality with @ref expected_addr.
///
/// @param option_type Option type.
/// @param expected_addr Desired address.
/// @param config Configuration obtained from the server.
void
verifyAddressOption
(
const
uint16_t
option_type
,
const
std
::
string
&
expected_addr
,
const
Dhcp6Client
::
Configuration
&
config
)
const
{
Option6AddrLstPtr
opt
=
boost
::
dynamic_pointer_cast
<
Option6AddrLst
>
(
config
.
findOption
(
option_type
));
ASSERT_TRUE
(
opt
)
<<
"option "
<<
option_type
<<
" not found or it "
"is of incorrect type"
;
Option6AddrLst
::
AddressContainer
addrs
=
opt
->
getAddresses
();
ASSERT_GE
(
addrs
.
size
(),
1
)
<<
"test failed for option type "
<<
option_type
;
EXPECT_EQ
(
expected_addr
,
addrs
[
0
].
toText
())
<<
"test failed for option type "
<<
option_type
;
}
/// @brief Verifies that the reservation is retrieved by the server
/// using one of the host identifiers.
///
...
...
@@ -154,10 +314,186 @@ public:
EXPECT_EQ
(
exp_ip_address
,
lease_client
.
addr_
.
toText
());
}
/// @brief Initiate exchange with DHCPv6 server.
///
/// This method initiates DHCPv6 message exchange between a specified
/// client a the server. The msg_type is used to indicate what kind
/// of exchange should be initiated. If the message type is a Renew
/// or Rebind, the 4-way handshake is made first. If the message type
/// is a Request, the Solicit-Advertise is done prior to this.
///
/// @param msg_type Message type to be sent to the server.
/// @param client Reference to a client to be used to initiate the
/// exchange with the server.
void
doExchange
(
const
uint16_t
msg_type
,
Dhcp6Client
&
client
);
/// @brief Verifies that host specific options override subnet specific
/// options.
///
/// Overriden options are requested with Option Request option.
///
/// @param msg_type DHCPv6 message type to be sent to the server. If the
/// message type is Renew or Rebind, the 4-way exchange is made prior to
/// sending a Renew or Rebind. For a Request case, the Solicit-Advertise
/// is also performed.
void
testOverrideRequestedOptions
(
const
uint16_t
msg_type
);
/// @brief Verifies that client receives options when they are solely
/// defined in the host scope (and not in the global or subnet scope).
///
/// @param msg_type DHCPv6 message type to be sent to the server. If the
/// message type is Renew or Rebind, the 4-way exchange is made prior to
/// sending a Renew or Rebind. For a Request case, the Solicit-Advertise
/// is also performed.
void
testHostOnlyOptions
(
const
uint16_t
msg_type
);
/// @brief Verifies that host specific vendor options override vendor
/// options defined in the global scope.
///
/// @param msg_type DHCPv6 message type to be sent to the server. If the
/// message type is Renew or Rebind, the 4-way exchange is made prior to
/// sending a Renew or Rebind. For a Request case, the Solicit-Advertise
/// is also performed.
void
testOverrideVendorOptions
(
const
uint16_t
msg_type
);
/// @brief Interface Manager's fake configuration control.
IfaceMgrTestConfig
iface_mgr_test_config_
;
};
void
HostTest
::
doExchange
(
const
uint16_t
msg_type
,
Dhcp6Client
&
client
)
{
switch
(
msg_type
)
{
case
DHCPV6_INFORMATION_REQUEST
:
ASSERT_NO_THROW
(
client
.
doInfRequest
());
break
;
case
DHCPV6_REQUEST
:
ASSERT_NO_THROW
(
client
.
doSARR
());
break
;
case
DHCPV6_SOLICIT
:
ASSERT_NO_THROW
(
client
.
doSolicit
());
break
;
case
DHCPV6_RENEW
:
ASSERT_NO_THROW
(
client
.
doSARR
());
ASSERT_NO_THROW
(
client
.
doRenew
());
break
;
case
DHCPV6_REBIND
:
ASSERT_NO_THROW
(
client
.
doSARR
());
ASSERT_NO_THROW
(
client
.
doRebind
());
break
;
default:
;
}
// Make sure that the server has responded with a Reply.
ASSERT_TRUE
(
client
.
getContext
().
response_
);
ASSERT_EQ
(
DHCPV6_REPLY
,
client
.
getContext
().
response_
->
getType
());
}
void
HostTest
::
testOverrideRequestedOptions
(
const
uint16_t
msg_type
)
{
Dhcp6Client
client
;
// Reservation has been made for a client with this DUID.
client
.
setDUID
(
"01:02:03:05"
);
// Request all options specified in the configuration.
client
.
requestOption
(
D6O_NAME_SERVERS
);
client
.
requestOption
(
D6O_NIS_SERVERS
);
client
.
requestOption
(
D6O_NISP_SERVERS
);
client
.
requestOption
(
D6O_SNTP_SERVERS
);
configure
(
CONFIGS
[
3
],
*
client
.
getServer
());
ASSERT_NO_FATAL_FAILURE
(
doExchange
(
msg_type
,
client
));
{
SCOPED_TRACE
(
"host specific dns-servers"
);
// Host specific DNS server should be used.
verifyAddressOption
(
D6O_NAME_SERVERS
,
"3000:1::234"
,
client
.
config_
);
}
{
SCOPED_TRACE
(
"host specific nis-servers"
);
// Host specific NIS server should be used.
verifyAddressOption
(
D6O_NIS_SERVERS
,
"3000:1::234"
,
client
.
config_
);
}
{
SCOPED_TRACE
(
"subnet specific sntp-servers"
);
// Subnet specific SNTP server should be used as it is not specified
// in a host scope.
verifyAddressOption
(
D6O_SNTP_SERVERS
,
"3000:2::123"
,
client
.
config_
);
}
{
SCOPED_TRACE
(
"global nisp-servers"
);
// Globally specified NISP server should be used as it is not
// specified in a host scope.
verifyAddressOption
(
D6O_NISP_SERVERS
,
"3000:3::123"
,
client
.
config_
);
}
}
void
HostTest
::
testHostOnlyOptions
(
const
uint16_t
msg_type
)
{
Dhcp6Client
client
;
client
.
setDUID
(
"01:02:03:05"
);
client
.
requestOption
(
D6O_NAME_SERVERS
);
client
.
requestOption
(
D6O_NIS_SERVERS
);
configure
(
CONFIGS
[
3
],
*
client
.
getServer
());
ASSERT_NO_FATAL_FAILURE
(
doExchange
(
msg_type
,
client
));
{
SCOPED_TRACE
(
"host specific dns-servers"
);
// DNS servers are specified only in a host scope.
verifyAddressOption
(
D6O_NAME_SERVERS
,
"3000:1::234"
,
client
.
config_
);
}
{
SCOPED_TRACE
(
"host specific nis-servers"
);
// NIS servers are specified only in a host scope.
verifyAddressOption
(
D6O_NIS_SERVERS
,
"3000:1::234"
,
client
.
config_
);
}
}
void
HostTest
::
testOverrideVendorOptions
(
const
uint16_t
msg_type
)
{
Dhcp6Client
client
;
client
.
setDUID
(
"01:02:03:05"
);
// Client needs to include Vendor Specific Information option
// with ORO suboption, which the server will use to determine
// which suboptions should be returned to the client.
OptionVendorPtr
opt_vendor
(
new
OptionVendor
(
Option
::
V6
,
VENDOR_ID_CABLE_LABS
));
// Include ORO with TFTP servers suboption code being requested.
opt_vendor
->
addOption
(
OptionPtr
(
new
OptionUint16
(
Option
::
V6
,
DOCSIS3_V6_ORO
,
DOCSIS3_V6_TFTP_SERVERS
)));
client
.
addExtraOption
(
opt_vendor
);
configure
(
CONFIGS
[
5
],
*
client
.
getServer
());
ASSERT_NO_FATAL_FAILURE
(
doExchange
(
msg_type
,
client
));
// Vendor Specific Information option should be returned by the server.
OptionVendorPtr
vendor_opt
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
client
.
config_
.
findOption
(
D6O_VENDOR_OPTS
));
ASSERT_TRUE
(
vendor_opt
);
// TFTP server suboption should be returned because it was requested
// with Option Request suboption.
Option6AddrLstPtr
tftp
=
boost
::
dynamic_pointer_cast
<
Option6AddrLst
>
(
vendor_opt
->
getOption
(
DOCSIS3_V6_TFTP_SERVERS
));
ASSERT_TRUE
(
tftp
);
// Address specified in the host scope should be used.
Option6AddrLst
::
AddressContainer
addrs
=
tftp
->
getAddresses
();
ASSERT_EQ
(
addrs
.
size
(),
1
);
EXPECT_EQ
(
"3000:1::234"
,
addrs
[
0
].
toText
());
}
// Test basic SARR scenarios against a server configured with one subnet
// containing two reservations. One reservation with a hostname, one
// without a hostname. Scenarios:
...
...
@@ -179,8 +515,8 @@ TEST_F(HostTest, basicSarrs) {
getCfgSubnets6
()
->
getAll
();
ASSERT_EQ
(
1
,
subnets
->
size
());
// Configure client to request IA_NA and a
A
ppend IA_NA option
//
to the client's message.
// Configure client to request IA_NA and append IA_NA option
// to the client's message.
client
.
setDUID
(
"01:02:03:04"
);
client
.
useNA
();
ASSERT_NO_THROW
(
client
.
useHint
(
100
,
200
,
64
,
"2001:db8:1:1::dead:beef"
));
...
...
@@ -376,4 +712,79 @@ TEST_F(HostTest, hostIdentifiersOrder) {
testReservationByIdentifier
(
client
,
2
,
"2001:db8:1::2"
);
}
// This test checks that host specific options override subnet specific
// options. Overridden options are requested with Option Request
// option (Information-request case).
TEST_F
(
HostTest
,
overrideRequestedOptionsInformationRequest
)
{
testOverrideRequestedOptions
(
DHCPV6_INFORMATION_REQUEST
);
}
// This test checks that host specific options override subnet specific
// options. Overridden options are requested with Option Request
// option (Request case).
TEST_F
(
HostTest
,
overrideRequestedOptionsRequest
)
{
testOverrideRequestedOptions
(
DHCPV6_REQUEST
);
}
// This test checks that host specific options override subnet specific
// options. Overridden options are requested with Option Request
// option (Renew case).
TEST_F
(
HostTest
,
overrideRequestedOptionsRenew
)
{
testOverrideRequestedOptions
(
DHCPV6_RENEW
);
}
// This test checks that host specific options override subnet specific
// options. Overridden options are requested with Option Request
// option (Rebind case).
TEST_F
(
HostTest
,
overrideRequestedOptionsRebind
)
{
testOverrideRequestedOptions
(
DHCPV6_REBIND
);
}
// This test checks that client receives options when they are
// solely defined in the host scope and not in the global or subnet
// scope (Information-request case).
TEST_F
(
HostTest
,
testHostOnlyOptionsInformationRequest
)
{
testHostOnlyOptions
(
DHCPV6_INFORMATION_REQUEST
);
}
// This test checks that client receives options when they are
// solely defined in the host scope and not in the global or subnet
// scope (Request case).
TEST_F
(
HostTest
,
testHostOnlyOptionsRequest
)
{
testHostOnlyOptions
(
DHCPV6_REQUEST
);
}
// This test checks that client receives options when they are
// solely defined in the host scope and not in the global or subnet
// scope (Renew case).
TEST_F
(
HostTest
,
testHostOnlyOptionsRenew
)
{
testHostOnlyOptions
(
DHCPV6_RENEW
);
}
// This test checks that client receives options when they are
// solely defined in the host scope and not in the global or subnet
// scope (Rebind case).
TEST_F
(
HostTest
,
testHostOnlyOptionsRebind
)
{
testHostOnlyOptions
(
DHCPV6_REBIND
);
}
// This test checks that host specific vendor options override vendor
// options defined in the global scope (Request case).
TEST_F
(
HostTest
,
overrideVendorOptionsRequest
)
{
testOverrideVendorOptions
(
DHCPV6_REQUEST
);
}
// This test checks that host specific vendor options override vendor
// options defined in the global scope (Renew case).
TEST_F
(
HostTest
,
overrideVendorOptionsRenew
)
{
testOverrideVendorOptions
(
DHCPV6_RENEW
);
}
// This test checks that host specific vendor options override vendor
// options defined in the global scope (Rebind case).
TEST_F
(
HostTest
,
overrideVendorOptionsRebind
)
{
testOverrideVendorOptions
(
DHCPV6_REBIND
);
}
}
// end of anonymous namespace
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment