Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
e3b2785c
Commit
e3b2785c
authored
Oct 13, 2016
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac5022'
parents
9f76f165
ef182c34
Changes
19
Hide whitespace changes
Inline
Side-by-side
doc/examples/kea6/multiple-options.json
View file @
e3b2785c
...
...
@@ -31,11 +31,16 @@
#
Defining
a
subnet.
There
are
2
DHCP
options
returned
to
the
#
clients
connected
to
this
subnet.
The
first
option
is
identified
#
by
the
name.
The
second
option
is
identified
by
the
code.
#
There
are
two
address
pools
defined
within
this
subnet.
Pool
#
specific
value
for
option
12
is
defined
for
the
pool:
#
2001
:db
8
:
1
::
1
-
2001
:db
8
:
1
::
100
.
Clients
obtaining
an
address
#
from
this
pool
will
be
assigned
option
12
with
a
value
of
#
3001
:cafe::
21
.
Clients
belonging
to
this
subnet
but
obtaining
#
addresses
from
the
other
pool
,
or
the
clients
obtaining
#
stateless
configuration
will
be
assigned
subnet
specific
value
#
of
option
12
,
i.e.
2001
:db
8
:
1
:
0
:ff
00
::
1
.
"subnet6"
:
[
{
"pools"
:
[
{
"pool"
:
"2001:db8:1::/80"
}
],
"subnet"
:
"2001:db8:1::/64"
,
"interface"
:
"ethX"
,
"option-data"
:
[
{
"name"
:
"dns-servers"
,
...
...
@@ -45,7 +50,23 @@
"code"
:
12
,
"data"
:
"2001:db8:1:0:ff00::1"
},
]
],
"pools"
:
[
{
"pool"
:
"2001:db8:1::1 - 2001:db8:1::100"
,
"option-data"
:
[
{
"code"
:
12
,
"data"
:
"3001:cafe::21"
}
]
},
{
"pool"
:
"2001:db8:1::500 - 2001:db8:2::1000"
}
],
"subnet"
:
"2001:db8:1::/64"
,
"interface"
:
"ethX"
,
}
]
},
...
...
doc/guide/dhcp6-srv.xml
View file @
e3b2785c
...
...
@@ -932,6 +932,7 @@ temporarily override a list of interface names and listen on all interfaces.
(Dhcp6/option-data), rather you should set only subnet-specific values
(Dhcp6/subnet[X]/option-data[Y]).
</para>
<para>
The following commands override the global
DNS servers option for a particular subnet, setting a single DNS
...
...
@@ -959,6 +960,48 @@ temporarily override a list of interface names and listen on all interfaces.
</screen>
</para>
<para>
In some cases it is useful to associate some options with an
address or prefix pool from which a client is assigned a lease. Pool
specific option values override subnet specific and global option
values. If the client is assigned multiple leases from different
pools, the server will assign options from all pools from which the
leases have been obtained. However, if the particular option is specified
in multiple pools from which the client obtains the leases, only one
instance of this option will be handed out to the client. The server's
administrator must not try to prioritize assignment of pool specific
options by trying to order pools declarations in the server
configuration. Future Kea releases may change the order in which
options are assigned from the pools without any notice.
</para>
<para>
The following configuration snippet demonstrates how to specify the
DNS servers option, which will be assigned to a client only if the
client obtains an address from the given pool:
<screen>
"Dhcp6": {
"subnet6": [
{
"pools": [
{
"pool": "2001:db8:1::100-2001:db8:1::300",
<userinput>
"option-data": [
{
"name": "dns-servers",
"data": "2001:db8:1::10"
}
]
</userinput>
}
]
},
...
],
...
}
</screen>
</para>
<para>
The currently supported standard DHCPv6 options are
listed in
<xref
linkend=
"dhcp6-std-options-list"
/>
.
...
...
src/bin/dhcp4/json_config_parser.cc
View file @
e3b2785c
...
...
@@ -32,6 +32,7 @@
#include <limits>
#include <iostream>
#include <netinet/in.h>
#include <vector>
#include <map>
...
...
@@ -61,7 +62,7 @@ public:
/// @param pools storage container in which to store the parsed pool
/// upon "commit"
Pool4Parser
(
const
std
::
string
&
param_name
,
PoolStoragePtr
pools
)
:
PoolParser
(
param_name
,
pools
)
{
:
PoolParser
(
param_name
,
pools
,
AF_INET
)
{
}
protected:
...
...
src/bin/dhcp6/dhcp6.spec
View file @
e3b2785c
...
...
@@ -441,17 +441,70 @@
"item_optional": false,
"item_default": 7200
},
{ "item_name": "pool",
"item_type": "list",
"item_optional": false,
"item_default": [],
"list_item_spec":
{
"item_name": "type",
"item_type": "string",
{ "item_name": "pools",
"item_type": "map",
"item_optional": true,
"item_default" : {},
"map_item_spec": [
{ "item_name": "pool",
"item_type": "list",
"item_optional": false,
"item_default": ""
}
"item_default": [],
"list_item_spec":
{
"item_name": "type",
"item_type": "string",
"item_optional": false,
"item_default": ""
}
},
{ "item_name": "option-data",
"item_type": "list",
"item_optional": false,
"item_default": [],
"item_description": "Holds a list of pool specific DHCP options.",
"list_item_spec":
{
"item_name": "single-option-data",
"item_type": "map",
"item_optional": false,
"item_default": {},
"item_description": "One of the pool specific DHCP options.",
"map_item_spec": [
{
"item_name": "name",
"item_type": "string",
"item_optional": false,
"item_default": "",
"item_description": "Option name."
},
{ "item_name": "code",
"item_type": "integer",
"item_optional": false,
"item_default": 0,
"item_description": "Option code."
},
{ "item_name": "data",
"item_type": "string",
"item_optional": false,
"item_default": "",
"item_description": "Option value."
},
{ "item_name": "csv-format",
"item_type": "boolean",
"item_optional": false,
"item_default": false,
"item_description": "Indicates if option value is specified as comma separated values."
},
{ "item_name": "space",
"item_type": "string",
"item_optional": false,
"item_default": "dhcp6",
"item_description": "Option space."
} ]
}
} ]
},
{ "item_name": "client-class",
...
...
@@ -506,7 +559,56 @@
"item_type": "integer",
"item_optional": false,
"item_default": 128
}]
},
{
"item_name": "option-data",
"item_type": "list",
"item_optional": false,
"item_default": [],
"item_description": "Holds a list of the pd-pool specific DHCP options.",
"list_item_spec":
{
"item_name": "single-option-data",
"item_type": "map",
"item_optional": false,
"item_default": {},
"item_description": "One of the pd-pool specific DHCP options.",
"map_item_spec": [
{
"item_name": "name",
"item_type": "string",
"item_optional": false,
"item_default": "",
"item_description": "Option name."
},
{ "item_name": "code",
"item_type": "integer",
"item_optional": false,
"item_default": 0,
"item_description": "Option code."
},
{ "item_name": "data",
"item_type": "string",
"item_optional": false,
"item_default": "",
"item_description": "Option value."
},
{ "item_name": "csv-format",
"item_type": "boolean",
"item_optional": false,
"item_default": false,
"item_description": "Indicates if option value is specified as comma separated values."
},
{ "item_name": "space",
"item_type": "string",
"item_optional": false,
"item_default": "dhcp6",
"item_description": "Option space."
} ]
}
} ]
}
},
{ "item_name": "option-data",
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
e3b2785c
...
...
@@ -820,6 +820,20 @@ Dhcpv6Srv::buildCfgOptionList(const Pkt6Ptr& question,
co_list
.
push_back
(
ctx
.
host_
->
getCfgOption6
());
}
// Secondly, pool specific options. Pools are defined within a subnet, so
// if there is no subnet, there is nothing to do.
if
(
ctx
.
subnet_
)
{
BOOST_FOREACH
(
const
AllocEngine
::
ResourceType
&
resource
,
ctx
.
allocated_resources_
)
{
PoolPtr
pool
=
ctx
.
subnet_
->
getPool
(
resource
.
second
==
128
?
Lease
::
TYPE_NA
:
Lease
::
TYPE_PD
,
resource
.
first
,
false
);
if
(
pool
&&
!
pool
->
getCfgOption
()
->
empty
())
{
co_list
.
push_back
(
pool
->
getCfgOption
());
}
}
};
// Next, subnet configured options.
if
(
ctx
.
subnet_
&&
!
ctx
.
subnet_
->
getCfgOption
()
->
empty
())
{
co_list
.
push_back
(
ctx
.
subnet_
->
getCfgOption
());
...
...
@@ -2316,6 +2330,9 @@ Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
}
}
processClientFqdn
(
solicit
,
response
,
ctx
);
assignLeases
(
solicit
,
response
,
ctx
);
copyClientOptions
(
solicit
,
response
);
CfgOptionList
co_list
;
buildCfgOptionList
(
solicit
,
ctx
,
co_list
);
...
...
@@ -2323,9 +2340,6 @@ Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
appendRequestedOptions
(
solicit
,
response
,
co_list
);
appendRequestedVendorOptions
(
solicit
,
response
,
ctx
,
co_list
);
processClientFqdn
(
solicit
,
response
,
ctx
);
assignLeases
(
solicit
,
response
,
ctx
);
// Only generate name change requests if sending a Reply as a result
// of receiving Rapid Commit option.
if
(
response
->
getType
()
==
DHCPV6_REPLY
)
{
...
...
@@ -2347,6 +2361,9 @@ Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
Pkt6Ptr
reply
(
new
Pkt6
(
DHCPV6_REPLY
,
request
->
getTransid
()));
processClientFqdn
(
request
,
reply
,
ctx
);
assignLeases
(
request
,
reply
,
ctx
);
copyClientOptions
(
request
,
reply
);
CfgOptionList
co_list
;
buildCfgOptionList
(
request
,
ctx
,
co_list
);
...
...
@@ -2354,8 +2371,6 @@ Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
appendRequestedOptions
(
request
,
reply
,
co_list
);
appendRequestedVendorOptions
(
request
,
reply
,
ctx
,
co_list
);
processClientFqdn
(
request
,
reply
,
ctx
);
assignLeases
(
request
,
reply
,
ctx
);
generateFqdn
(
reply
);
createNameChangeRequests
(
reply
,
ctx
);
...
...
@@ -2374,6 +2389,9 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
Pkt6Ptr
reply
(
new
Pkt6
(
DHCPV6_REPLY
,
renew
->
getTransid
()));
processClientFqdn
(
renew
,
reply
,
ctx
);
extendLeases
(
renew
,
reply
,
ctx
);
copyClientOptions
(
renew
,
reply
);
CfgOptionList
co_list
;
buildCfgOptionList
(
renew
,
ctx
,
co_list
);
...
...
@@ -2381,8 +2399,6 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
appendRequestedOptions
(
renew
,
reply
,
co_list
);
appendRequestedVendorOptions
(
renew
,
reply
,
ctx
,
co_list
);
processClientFqdn
(
renew
,
reply
,
ctx
);
extendLeases
(
renew
,
reply
,
ctx
);
generateFqdn
(
reply
);
createNameChangeRequests
(
reply
,
ctx
);
...
...
@@ -2401,6 +2417,9 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
Pkt6Ptr
reply
(
new
Pkt6
(
DHCPV6_REPLY
,
rebind
->
getTransid
()));
processClientFqdn
(
rebind
,
reply
,
ctx
);
extendLeases
(
rebind
,
reply
,
ctx
);
copyClientOptions
(
rebind
,
reply
);
CfgOptionList
co_list
;
buildCfgOptionList
(
rebind
,
ctx
,
co_list
);
...
...
@@ -2408,8 +2427,6 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
appendRequestedOptions
(
rebind
,
reply
,
co_list
);
appendRequestedVendorOptions
(
rebind
,
reply
,
ctx
,
co_list
);
processClientFqdn
(
rebind
,
reply
,
ctx
);
extendLeases
(
rebind
,
reply
,
ctx
);
generateFqdn
(
reply
);
createNameChangeRequests
(
reply
,
ctx
);
...
...
src/bin/dhcp6/json_config_parser.cc
View file @
e3b2785c
...
...
@@ -43,6 +43,7 @@
#include <iostream>
#include <limits>
#include <map>
#include <netinet/in.h>
#include <vector>
#include <stdint.h>
...
...
@@ -78,7 +79,7 @@ public:
/// @param pools storage container in which to store the parsed pool
/// upon "commit"
Pool6Parser
(
const
std
::
string
&
param_name
,
PoolStoragePtr
pools
)
:
PoolParser
(
param_name
,
pools
)
{
:
PoolParser
(
param_name
,
pools
,
AF_INET6
)
{
}
protected:
...
...
@@ -151,7 +152,8 @@ public:
/// upon "commit"
PdPoolParser
(
const
std
::
string
&
,
PoolStoragePtr
pools
)
:
uint32_values_
(
new
Uint32Storage
()),
string_values_
(
new
StringStorage
()),
pools_
(
pools
)
{
string_values_
(
new
StringStorage
()),
pools_
(
pools
),
options_
(
new
CfgOption
())
{
if
(
!
pools_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"PdPoolParser context storage may not be NULL"
);
...
...
@@ -180,6 +182,12 @@ public:
Uint32ParserPtr
code_parser
(
new
Uint32Parser
(
entry
,
uint32_values_
));
parser
=
code_parser
;
}
else
if
(
entry
==
"option-data"
)
{
OptionDataListParserPtr
option_parser
(
new
OptionDataListParser
(
entry
,
options_
,
AF_INET6
));
parser
=
option_parser
;
}
else
{
isc_throw
(
DhcpConfigError
,
"unsupported parameter: "
<<
entry
<<
" ("
<<
param
.
second
->
getPosition
()
<<
")"
);
...
...
@@ -199,6 +207,8 @@ public:
// Attempt to construct the local pool.
pool_
.
reset
(
new
Pool6
(
Lease
::
TYPE_PD
,
IOAddress
(
addr_str
),
prefix_len
,
delegated_len
));
// Merge options specified for a pool into pool configuration.
options_
->
copyTo
(
*
pool_
->
getCfgOption
());
}
catch
(
const
std
::
exception
&
ex
)
{
// Some parameters don't exist or are invalid. Since we are not
// aware whether they don't exist or are invalid, let's append
...
...
@@ -229,6 +239,9 @@ protected:
/// Pointer to storage to which the local pool is written upon commit.
isc
::
dhcp
::
PoolStoragePtr
pools_
;
/// A storage for pool specific option values.
CfgOptionPtr
options_
;
};
/// @brief Parser for a list of prefix delegation pools.
...
...
src/bin/dhcp6/tests/config_parser_unittest.cc
View file @
e3b2785c
...
...
@@ -2556,6 +2556,154 @@ TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) {
sizeof
(
user_class_expected
));
}
// This test verifies that it is possible to specify options on
// pool levels.
TEST_F
(
Dhcp6ParserTest
,
optionDataMultiplePools
)
{
ConstElementPtr
x
;
string
config
=
"{ "
+
genIfaceConfig
()
+
","
"
\"
preferred-lifetime
\"
: 3000,"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
subnet6
\"
: [ { "
"
\"
pools
\"
: [ { "
"
\"
pool
\"
:
\"
2001:db8:1::10 - 2001:db8:1::100
\"
,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
subscriber-id
\"
,"
"
\"
data
\"
:
\"
0102030405060708090A
\"
,"
"
\"
csv-format
\"
: False"
" } ]"
" },"
" {"
"
\"
pool
\"
:
\"
2001:db8:1::300 - 2001:db8:1::400
\"
,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
user-class
\"
,"
"
\"
data
\"
:
\"
FFFEFDFCFB
\"
,"
"
\"
csv-format
\"
: False"
" } ]"
" } ],"
"
\"
pd-pools
\"
: [ { "
"
\"
prefix
\"
:
\"
3000::
\"
,"
"
\"
prefix-len
\"
: 48,"
"
\"
delegated-len
\"
: 64,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
subscriber-id
\"
,"
"
\"
data
\"
:
\"
112233445566
\"
,"
"
\"
csv-format
\"
: False"
" } ]"
" },"
" {"
"
\"
prefix
\"
:
\"
3001::
\"
,"
"
\"
prefix-len
\"
: 48,"
"
\"
delegated-len
\"
: 64,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
user-class
\"
,"
"
\"
data
\"
:
\"
aabbccddee
\"
,"
"
\"
csv-format
\"
: False"
" } ]"
" } ],"
"
\"
subnet
\"
:
\"
2001:db8:1::/64
\"
"
" } ],"
"
\"
valid-lifetime
\"
: 4000 }"
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
EXPECT_NO_THROW
(
x
=
configureDhcp6Server
(
srv_
,
json
));
checkResult
(
x
,
0
);
Subnet6Ptr
subnet
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgSubnets6
()
->
selectSubnet
(
IOAddress
(
"2001:db8:1::5"
),
classify_
);
ASSERT_TRUE
(
subnet
);
PoolPtr
pool
=
subnet
->
getPool
(
Lease
::
TYPE_PD
,
IOAddress
(
"3000::"
),
false
);
ASSERT_TRUE
(
pool
);
Pool6Ptr
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
pool
);
ASSERT_TRUE
(
pool6
);
OptionContainerPtr
options1
=
pool6
->
getCfgOption
()
->
getAll
(
"dhcp6"
);
ASSERT_EQ
(
1
,
options1
->
size
());
// Get the search index. Index #1 is to search using option code.
const
OptionContainerTypeIndex
&
idx1
=
options1
->
get
<
1
>
();
// Get the options for specified index. Expecting one option to be
// returned but in theory we may have multiple options with the same
// code so we get the range.
std
::
pair
<
OptionContainerTypeIndex
::
const_iterator
,
OptionContainerTypeIndex
::
const_iterator
>
range1
=
idx1
.
equal_range
(
D6O_SUBSCRIBER_ID
);
// Expect a single Subscriber ID option instance.
ASSERT_EQ
(
1
,
std
::
distance
(
range1
.
first
,
range1
.
second
));
const
uint8_t
subscriber_id_expected
[]
=
{
0x11
,
0x22
,
0x33
,
0x44
,
0x55
,
0x66
};
// Check if option is valid in terms of code and carried data.
testOption
(
*
range1
.
first
,
D6O_SUBSCRIBER_ID
,
subscriber_id_expected
,
sizeof
(
subscriber_id_expected
));
// Test another pool in the same way.
pool
=
subnet
->
getPool
(
Lease
::
TYPE_PD
,
IOAddress
(
"3001::"
),
false
);
ASSERT_TRUE
(
pool
);
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
pool
);
ASSERT_TRUE
(
pool6
);
OptionContainerPtr
options2
=
pool6
->
getCfgOption
()
->
getAll
(
"dhcp6"
);
ASSERT_EQ
(
1
,
options2
->
size
());
const
OptionContainerTypeIndex
&
idx2
=
options2
->
get
<
1
>
();
std
::
pair
<
OptionContainerTypeIndex
::
const_iterator
,
OptionContainerTypeIndex
::
const_iterator
>
range2
=
idx2
.
equal_range
(
D6O_USER_CLASS
);
ASSERT_EQ
(
1
,
std
::
distance
(
range2
.
first
,
range2
.
second
));
const
uint8_t
user_class_expected
[]
=
{
0xAA
,
0xBB
,
0xCC
,
0xDD
,
0xEE
};
testOption
(
*
range2
.
first
,
D6O_USER_CLASS
,
user_class_expected
,
sizeof
(
user_class_expected
));
// Test options in NA pools.
pool
=
subnet
->
getPool
(
Lease
::
TYPE_NA
,
IOAddress
(
"2001:db8:1::10"
));
ASSERT_TRUE
(
pool
);
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
pool
);
ASSERT_TRUE
(
pool6
);
OptionContainerPtr
options3
=
pool6
->
getCfgOption
()
->
getAll
(
"dhcp6"
);
ASSERT_EQ
(
1
,
options3
->
size
());
const
OptionContainerTypeIndex
&
idx3
=
options3
->
get
<
1
>
();
std
::
pair
<
OptionContainerTypeIndex
::
const_iterator
,
OptionContainerTypeIndex
::
const_iterator
>
range3
=
idx3
.
equal_range
(
D6O_SUBSCRIBER_ID
);
ASSERT_EQ
(
1
,
std
::
distance
(
range3
.
first
,
range3
.
second
));
const
uint8_t
subscriber_id_expected2
[]
=
{
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x06
,
0x07
,
0x08
,
0x09
,
0x0A
};
testOption
(
*
range3
.
first
,
D6O_SUBSCRIBER_ID
,
subscriber_id_expected2
,
sizeof
(
subscriber_id_expected2
));
pool
=
subnet
->
getPool
(
Lease
::
TYPE_NA
,
IOAddress
(
"2001:db8:1::300"
));
ASSERT_TRUE
(
pool
);
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
pool
);
ASSERT_TRUE
(
pool6
);
OptionContainerPtr
options4
=
pool6
->
getCfgOption
()
->
getAll
(
"dhcp6"
);
ASSERT_EQ
(
1
,
options4
->
size
());
const
OptionContainerTypeIndex
&
idx4
=
options4
->
get
<
1
>
();
std
::
pair
<
OptionContainerTypeIndex
::
const_iterator
,
OptionContainerTypeIndex
::
const_iterator
>
range4
=
idx4
.
equal_range
(
D6O_USER_CLASS
);
ASSERT_EQ
(
1
,
std
::
distance
(
range4
.
first
,
range4
.
second
));
const
uint8_t
user_class_expected2
[]
=
{
0xFF
,
0xFE
,
0xFD
,
0xFC
,
0xFB
};
testOption
(
*
range4
.
first
,
D6O_USER_CLASS
,
user_class_expected2
,
sizeof
(
user_class_expected2
));
}
// The goal of this test is to check that the option carrying a boolean
// value can be configured using one of the values: "true", "false", "0"
// or "1".
...
...
src/bin/dhcp6/tests/dhcp6_client.cc
View file @
e3b2785c
...
...
@@ -8,11 +8,12 @@
#include <dhcp/dhcp6.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp/option_custom.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_vendor.h>
#include <dhcp/option6_addrlst.h>
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option6_status_code.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_vendor.h>
#include <dhcp/pkt6.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/pool.h>
...
...
@@ -20,6 +21,7 @@
#include <util/buffer.h>
#include <boost/foreach.hpp>
#include <boost/pointer_cast.hpp>
#include <algorithm>
#include <cstdlib>
#include <time.h>
...
...
@@ -803,6 +805,20 @@ Dhcp6Client::hasLeaseWithZeroLifetimeForPrefix(const asiolink::IOAddress& prefix
return
(
false
);
}
bool
Dhcp6Client
::
hasOptionWithAddress
(
const
uint16_t
option_type
,
const
std
::
string
&
expected_address
)
const
{
Option6AddrLstPtr
opt
=
boost
::
dynamic_pointer_cast
<
Option6AddrLst
>
(
config_
.
findOption
(
option_type
));
if
(
opt
)
{
Option6AddrLst
::
AddressContainer
addrs
=
opt
->
getAddresses
();
if
(
!
addrs
.
empty
())
{
return
(
std
::
find
(
addrs
.
begin
(),
addrs
.
end
(),
IOAddress
(
expected_address
))
!=
addrs
.
end
());
}
}
return
(
false
);
}
uint16_t
Dhcp6Client
::
getStatusCode
(
const
uint32_t
iaid
)
const
{
...
...
src/bin/dhcp6/tests/dhcp6_client.h
View file @
e3b2785c
...
...
@@ -468,6 +468,19 @@ public:
bool
hasLeaseWithZeroLifetimeForPrefix
(
const
asiolink
::
IOAddress
&
prefix
,
const
uint8_t
prefix_len
)
const
;