Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Adam Osuchowski
Kea
Commits
0a61518a
Commit
0a61518a
authored
Jul 25, 2017
by
Marcin Siodelski
Committed by
Tomek Mrugalski
Aug 15, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[5315] Moved Subnet parsers from DHCP binaries to libdhcpsrv.
parent
433313ef
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1284 additions
and
666 deletions
+1284
-666
src/bin/dhcp4/json_config_parser.cc
src/bin/dhcp4/json_config_parser.cc
+1
-267
src/bin/dhcp6/dhcp6_messages.mes
src/bin/dhcp6/dhcp6_messages.mes
+0
-9
src/bin/dhcp6/json_config_parser.cc
src/bin/dhcp6/json_config_parser.cc
+1
-385
src/lib/dhcpsrv/Makefile.am
src/lib/dhcpsrv/Makefile.am
+3
-0
src/lib/dhcpsrv/dhcpsrv_messages.mes
src/lib/dhcpsrv/dhcpsrv_messages.mes
+13
-0
src/lib/dhcpsrv/parsers/client_class_def_parser.cc
src/lib/dhcpsrv/parsers/client_class_def_parser.cc
+1
-0
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
src/lib/dhcpsrv/parsers/dhcp_parsers.cc
+461
-0
src/lib/dhcpsrv/parsers/dhcp_parsers.h
src/lib/dhcpsrv/parsers/dhcp_parsers.h
+274
-1
src/lib/dhcpsrv/parsers/host_reservation_parser.cc
src/lib/dhcpsrv/parsers/host_reservation_parser.cc
+4
-4
src/lib/dhcpsrv/parsers/option_data_parser.cc
src/lib/dhcpsrv/parsers/option_data_parser.cc
+348
-0
src/lib/dhcpsrv/parsers/option_data_parser.h
src/lib/dhcpsrv/parsers/option_data_parser.h
+177
-0
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
+1
-0
No files found.
src/bin/dhcp4/json_config_parser.cc
View file @
0a61518a
...
...
@@ -21,6 +21,7 @@
#include <dhcpsrv/parsers/host_reservation_parser.h>
#include <dhcpsrv/parsers/host_reservations_list_parser.h>
#include <dhcpsrv/parsers/ifaces_config_parser.h>
#include <dhcpsrv/parsers/option_data_parser.h>
#include <dhcpsrv/timer_mgr.h>
#include <hooks/hooks_parser.h>
#include <config/command_mgr.h>
...
...
@@ -46,273 +47,6 @@ using namespace isc::hooks;
namespace
{
/// @brief Parser for IPv4 pool definitions.
///
/// This is the IPv4 derivation of the PoolParser class and handles pool
/// definitions, i.e. a list of entries of one of two syntaxes: min-max and
/// prefix/len for IPv4 pools. Pool4 objects are created and stored in chosen
/// PoolStorage container.
///
/// It is useful for parsing Dhcp4/subnet4[X]/pool parameters.
class
Pool4Parser
:
public
PoolParser
{
protected:
/// @brief Creates a Pool4 object given a IPv4 prefix and the prefix length.
///
/// @param addr is the IPv4 prefix of the pool.
/// @param len is the prefix length.
/// @param ignored dummy parameter to provide symmetry between the
/// PoolParser derivations. The V6 derivation requires a third value.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr
poolMaker
(
IOAddress
&
addr
,
uint32_t
len
,
int32_t
)
{
return
(
PoolPtr
(
new
Pool4
(
addr
,
len
)));
}
/// @brief Creates a Pool4 object given starting and ending IPv4 addresses.
///
/// @param min is the first IPv4 address in the pool.
/// @param max is the last IPv4 address in the pool.
/// @param ignored dummy parameter to provide symmetry between the
/// PoolParser derivations. The V6 derivation requires a third value.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr
poolMaker
(
IOAddress
&
min
,
IOAddress
&
max
,
int32_t
)
{
return
(
PoolPtr
(
new
Pool4
(
min
,
max
)));
}
};
/// @brief Specialization of the pool list parser for DHCPv4
class
Pools4ListParser
:
PoolsListParser
{
public:
/// @brief parses the actual structure
///
/// This method parses the actual list of pools.
///
/// @param pools storage container in which to store the parsed pool.
/// @param pools_list a list of pool structures
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
void
parse
(
PoolStoragePtr
pools
,
isc
::
data
::
ConstElementPtr
pools_list
)
{
BOOST_FOREACH
(
ConstElementPtr
pool
,
pools_list
->
listValue
())
{
Pool4Parser
parser
;
parser
.
parse
(
pools
,
pool
,
AF_INET
);
}
}
};
/// @anchor Subnet4ConfigParser
/// @brief This class parses a single IPv4 subnet.
///
/// This is the IPv4 derivation of the SubnetConfigParser class and it parses
/// the whole subnet definition. It creates parsersfor received configuration
/// parameters as needed.
class
Subnet4ConfigParser
:
public
SubnetConfigParser
{
public:
/// @brief Constructor
///
/// stores global scope parameters, options, option definitions.
Subnet4ConfigParser
()
:
SubnetConfigParser
(
AF_INET
)
{
}
/// @brief Parses a single IPv4 subnet configuration and adds to the
/// Configuration Manager.
///
/// @param subnet A new subnet being configured.
/// @return a pointer to created Subnet4 object
Subnet4Ptr
parse
(
ConstElementPtr
subnet
)
{
/// Parse Pools first.
ConstElementPtr
pools
=
subnet
->
get
(
"pools"
);
if
(
pools
)
{
Pools4ListParser
parser
;
parser
.
parse
(
pools_
,
pools
);
}
SubnetPtr
generic
=
SubnetConfigParser
::
parse
(
subnet
);
if
(
!
generic
)
{
isc_throw
(
DhcpConfigError
,
"Failed to create an IPv4 subnet ("
<<
subnet
->
getPosition
()
<<
")"
);
}
Subnet4Ptr
sn4ptr
=
boost
::
dynamic_pointer_cast
<
Subnet4
>
(
subnet_
);
if
(
!
sn4ptr
)
{
// If we hit this, it is a programming error.
isc_throw
(
Unexpected
,
"Invalid Subnet4 cast in Subnet4ConfigParser::parse"
);
}
// Set relay information if it was parsed
if
(
relay_info_
)
{
sn4ptr
->
setRelayInfo
(
*
relay_info_
);
}
// Parse Host Reservations for this subnet if any.
ConstElementPtr
reservations
=
subnet
->
get
(
"reservations"
);
if
(
reservations
)
{
HostCollection
hosts
;
HostReservationsListParser
<
HostReservationParser4
>
parser
;
parser
.
parse
(
subnet_
->
getID
(),
reservations
,
hosts
);
for
(
auto
h
=
hosts
.
begin
();
h
!=
hosts
.
end
();
++
h
)
{
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgHosts
()
->
add
(
*
h
);
}
}
return
(
sn4ptr
);
}
protected:
/// @brief Instantiates the IPv4 Subnet based on a given IPv4 address
/// and prefix length.
///
/// @param addr is IPv4 address of the subnet.
/// @param len is the prefix length
void
initSubnet
(
isc
::
data
::
ConstElementPtr
params
,
isc
::
asiolink
::
IOAddress
addr
,
uint8_t
len
)
{
// The renew-timer and rebind-timer are optional. If not set, the
// option 58 and 59 will not be sent to a client. In this case the
// client will use default values based on the valid-lifetime.
Triplet
<
uint32_t
>
t1
=
getInteger
(
params
,
"renew-timer"
);
Triplet
<
uint32_t
>
t2
=
getInteger
(
params
,
"rebind-timer"
);
// The valid-lifetime is mandatory. It may be specified for a
// particular subnet. If not, the global value should be present.
// If there is no global value, exception is thrown.
Triplet
<
uint32_t
>
valid
=
getInteger
(
params
,
"valid-lifetime"
);
// Subnet ID is optional. If it is not supplied the value of 0 is used,
// which means autogenerate. The value was inserted earlier by calling
// SimpleParser4::setAllDefaults.
SubnetID
subnet_id
=
static_cast
<
SubnetID
>
(
getInteger
(
params
,
"id"
));
stringstream
s
;
s
<<
addr
<<
"/"
<<
static_cast
<
int
>
(
len
)
<<
" with params: "
;
// t1 and t2 are optional may be not specified.
if
(
!
t1
.
unspecified
())
{
s
<<
"t1="
<<
t1
<<
", "
;
}
if
(
!
t2
.
unspecified
())
{
s
<<
"t2="
<<
t2
<<
", "
;
}
s
<<
"valid-lifetime="
<<
valid
;
LOG_INFO
(
dhcp4_logger
,
DHCP4_CONFIG_NEW_SUBNET
).
arg
(
s
.
str
());
Subnet4Ptr
subnet4
(
new
Subnet4
(
addr
,
len
,
t1
,
t2
,
valid
,
subnet_id
));
subnet_
=
subnet4
;
// Set the match-client-id value for the subnet. It is always present.
// If not explicitly specified, the default value was filled in when
// SimpleParser4::setAllDefaults was called.
bool
match_client_id
=
getBoolean
(
params
,
"match-client-id"
);
subnet4
->
setMatchClientId
(
match_client_id
);
// Set next-server. The default value is 0.0.0.0. Nevertheless, the
// user could have messed that up by specifying incorrect value.
// To avoid using 0.0.0.0, user can specify "".
string
next_server
;
try
{
next_server
=
getString
(
params
,
"next-server"
);
if
(
!
next_server
.
empty
())
{
subnet4
->
setSiaddr
(
IOAddress
(
next_server
));
}
}
catch
(...)
{
ConstElementPtr
next
=
params
->
get
(
"next-server"
);
string
pos
;
if
(
next
)
pos
=
next
->
getPosition
().
str
();
else
pos
=
params
->
getPosition
().
str
();
isc_throw
(
DhcpConfigError
,
"invalid parameter next-server : "
<<
next_server
<<
"("
<<
pos
<<
")"
);
}
// 4o6 specific parameter: 4o6-interface. If not explicitly specified,
// it will have the default value of "".
string
iface4o6
=
getString
(
params
,
"4o6-interface"
);
if
(
!
iface4o6
.
empty
())
{
subnet4
->
get4o6
().
setIface4o6
(
iface4o6
);
subnet4
->
get4o6
().
enabled
(
true
);
}
// 4o6 specific parameter: 4o6-subnet. If not explicitly specified, it
// will have the default value of "".
string
subnet4o6
=
getString
(
params
,
"4o6-subnet"
);
if
(
!
subnet4o6
.
empty
())
{
size_t
slash
=
subnet4o6
.
find
(
"/"
);
if
(
slash
==
std
::
string
::
npos
)
{
isc_throw
(
DhcpConfigError
,
"Missing / in the 4o6-subnet parameter:"
<<
subnet4o6
<<
", expected format: prefix6/length"
);
}
string
prefix
=
subnet4o6
.
substr
(
0
,
slash
);
string
lenstr
=
subnet4o6
.
substr
(
slash
+
1
);
uint8_t
len
=
128
;
try
{
len
=
boost
::
lexical_cast
<
unsigned
int
>
(
lenstr
.
c_str
());
}
catch
(
const
boost
::
bad_lexical_cast
&
)
{
isc_throw
(
DhcpConfigError
,
"Invalid prefix length specified in "
"4o6-subnet parameter: "
<<
subnet4o6
<<
", expected 0..128 value"
);
}
subnet4
->
get4o6
().
setSubnet4o6
(
IOAddress
(
prefix
),
len
);
subnet4
->
get4o6
().
enabled
(
true
);
}
// Try 4o6 specific parameter: 4o6-interface-id
std
::
string
ifaceid
=
getString
(
params
,
"4o6-interface-id"
);
if
(
!
ifaceid
.
empty
())
{
OptionBuffer
tmp
(
ifaceid
.
begin
(),
ifaceid
.
end
());
OptionPtr
opt
(
new
Option
(
Option
::
V6
,
D6O_INTERFACE_ID
,
tmp
));
subnet4
->
get4o6
().
setInterfaceId
(
opt
);
subnet4
->
get4o6
().
enabled
(
true
);
}
/// client-class processing is now generic and handled in the common
/// code (see @ref isc::data::SubnetConfigParser::createSubnet)
}
};
/// @brief this class parses list of DHCP4 subnets
///
/// This is a wrapper parser that handles the whole list of Subnet4
/// definitions. It iterates over all entries and creates Subnet4ConfigParser
/// for each entry.
class
Subnets4ListConfigParser
:
public
isc
::
data
::
SimpleParser
{
public:
/// @brief parses contents of the list
///
/// Iterates over all entries on the list, parses its content
/// (by instantiating Subnet6ConfigParser) and adds to specified
/// configuration.
///
/// @param subnets_list pointer to a list of IPv4 subnets
/// @return number of subnets created
size_t
parse
(
SrvConfigPtr
cfg
,
ConstElementPtr
subnets_list
)
{
size_t
cnt
=
0
;
BOOST_FOREACH
(
ConstElementPtr
subnet_json
,
subnets_list
->
listValue
())
{
Subnet4ConfigParser
parser
;
Subnet4Ptr
subnet
=
parser
.
parse
(
subnet_json
);
if
(
subnet
)
{
// Adding a subnet to the Configuration Manager may fail if the
// subnet id is invalid (duplicate). Thus, we catch exceptions
// here to append a position in the configuration string.
try
{
cfg
->
getCfgSubnets4
()
->
add
(
subnet
);
cnt
++
;
}
catch
(
const
std
::
exception
&
ex
)
{
isc_throw
(
DhcpConfigError
,
ex
.
what
()
<<
" ("
<<
subnet_json
->
getPosition
()
<<
")"
);
}
}
}
return
(
cnt
);
}
};
/// @brief Parser that takes care of global DHCPv4 parameters.
///
/// See @ref parse method for a list of supported parameters.
...
...
src/bin/dhcp6/dhcp6_messages.mes
View file @
0a61518a
...
...
@@ -97,15 +97,6 @@ If this is an initial configuration (during server's startup) the server
will fail to start. If this is a dynamic reconfiguration attempt the
server will continue to use an old configuration.
% DHCP6_CONFIG_NEW_SUBNET a new subnet has been added to configuration: %1
This is an informational message reporting that the configuration has
been extended to include the specified subnet.
% DHCP6_CONFIG_OPTION_DUPLICATE multiple options with the code: %1 added to the subnet: %2
This warning message is issued on an attempt to configure multiple options with the
same option code for the particular subnet. Adding multiple options is uncommon
for DHCPv6, but it is not prohibited.
% DHCP6_CONFIG_RECEIVED received configuration: %1
A debug message listing the configuration received by the DHCPv6 server.
The source of that configuration depends on used configuration backend.
...
...
src/bin/dhcp6/json_config_parser.cc
View file @
0a61518a
...
...
@@ -30,6 +30,7 @@
#include <dhcpsrv/parsers/host_reservation_parser.h>
#include <dhcpsrv/parsers/host_reservations_list_parser.h>
#include <dhcpsrv/parsers/ifaces_config_parser.h>
#include <dhcpsrv/parsers/option_data_parser.h>
#include <hooks/hooks_parser.h>
#include <log/logger_support.h>
#include <util/encode/hex.h>
...
...
@@ -63,391 +64,6 @@ typedef boost::shared_ptr<BooleanParser> BooleanParserPtr;
typedef
boost
::
shared_ptr
<
StringParser
>
StringParserPtr
;
typedef
boost
::
shared_ptr
<
Uint32Parser
>
Uint32ParserPtr
;
/// @brief Parser for IPv6 pool definitions.
///
/// This is the IPv6 derivation of the PoolParser class and handles pool
/// definitions, i.e. a list of entries of one of two syntaxes: min-max and
/// prefix/len for IPv6 pools. Pool6 objects are created and stored in chosen
/// PoolStorage container.
///
/// It is useful for parsing Dhcp6/subnet6[X]/pool parameters.
class
Pool6Parser
:
public
PoolParser
{
protected:
/// @brief Creates a Pool6 object given a IPv6 prefix and the prefix length.
///
/// @param addr is the IPv6 prefix of the pool.
/// @param len is the prefix length.
/// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
/// passed in as an int32_t and cast to PoolType to accommodate a
/// polymorphic interface.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr
poolMaker
(
IOAddress
&
addr
,
uint32_t
len
,
int32_t
ptype
)
{
return
(
PoolPtr
(
new
Pool6
(
static_cast
<
isc
::
dhcp
::
Lease
::
Type
>
(
ptype
),
addr
,
len
)));
}
/// @brief Creates a Pool6 object given starting and ending IPv6 addresses.
///
/// @param min is the first IPv6 address in the pool.
/// @param max is the last IPv6 address in the pool.
/// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
/// passed in as an int32_t and cast to PoolType to accommodate a
/// polymorphic interface.
/// @return returns a PoolPtr to the new Pool4 object.
PoolPtr
poolMaker
(
IOAddress
&
min
,
IOAddress
&
max
,
int32_t
ptype
)
{
return
(
PoolPtr
(
new
Pool6
(
static_cast
<
isc
::
dhcp
::
Lease
::
Type
>
(
ptype
),
min
,
max
)));
}
};
/// @brief Specialization of the pool list parser for DHCPv6
class
Pools6ListParser
:
PoolsListParser
{
public:
/// @brief parses the actual structure
///
/// This method parses the actual list of pools.
///
/// @param pools storage container in which to store the parsed pool.
/// @param pools_list a list of pool structures
/// @throw isc::dhcp::DhcpConfigError when pool parsing fails
void
parse
(
PoolStoragePtr
pools
,
isc
::
data
::
ConstElementPtr
pools_list
)
{
BOOST_FOREACH
(
ConstElementPtr
pool
,
pools_list
->
listValue
())
{
Pool6Parser
parser
;
parser
.
parse
(
pools
,
pool
,
AF_INET6
);
}
}
};
/// @brief Parser for IPv6 prefix delegation definitions.
///
/// This class handles prefix delegation pool definitions for IPv6 subnets
/// Pool6 objects are created and stored in the given PoolStorage container.
///
/// PdPool definitions currently support three elements: prefix, prefix-len,
/// and delegated-len, as shown in the example JSON text below:
///
/// @code
///
/// {
/// "prefix": "2001:db8:1::",
/// "prefix-len": 64,
/// "delegated-len": 128
/// }
/// @endcode
///
class
PdPoolParser
:
public
isc
::
data
::
SimpleParser
{
public:
/// @brief Constructor.
///
PdPoolParser
()
:
options_
(
new
CfgOption
())
{
}
/// @brief Builds a prefix delegation pool from the given configuration
///
/// This function parses configuration entries and creates an instance
/// of a dhcp::Pool6 configured for prefix delegation.
///
/// @param pools storage container in which to store the parsed pool.
/// @param pd_pool_ pointer to an element that holds configuration entries
/// that define a prefix delegation pool.
///
/// @throw DhcpConfigError if configuration parsing fails.
void
parse
(
PoolStoragePtr
pools
,
ConstElementPtr
pd_pool_
)
{
std
::
string
addr_str
=
getString
(
pd_pool_
,
"prefix"
);
uint8_t
prefix_len
=
getUint8
(
pd_pool_
,
"prefix-len"
);
uint8_t
delegated_len
=
getUint8
(
pd_pool_
,
"delegated-len"
);
std
::
string
excluded_prefix_str
=
"::"
;
if
(
pd_pool_
->
contains
(
"excluded-prefix"
))
{
excluded_prefix_str
=
getString
(
pd_pool_
,
"excluded-prefix"
);
}
uint8_t
excluded_prefix_len
=
0
;
if
(
pd_pool_
->
contains
(
"excluded-prefix-len"
))
{
excluded_prefix_len
=
getUint8
(
pd_pool_
,
"excluded-prefix-len"
);
}
ConstElementPtr
option_data
=
pd_pool_
->
get
(
"option-data"
);
if
(
option_data
)
{
OptionDataListParser
opts_parser
(
AF_INET6
);
opts_parser
.
parse
(
options_
,
option_data
);
}
ConstElementPtr
user_context
=
pd_pool_
->
get
(
"user-context"
);
if
(
user_context
)
{
user_context_
=
user_context
;
}
// Check the pool parameters. It will throw an exception if any
// of the required parameters are invalid.
try
{
// Attempt to construct the local pool.
pool_
.
reset
(
new
Pool6
(
IOAddress
(
addr_str
),
prefix_len
,
delegated_len
,
IOAddress
(
excluded_prefix_str
),
excluded_prefix_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
// the position of the pool map element.
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
ex
.
what
()
<<
" ("
<<
pd_pool_
->
getPosition
()
<<
")"
);
}
if
(
user_context_
)
{
pool_
->
setUserContext
(
user_context_
);
}
// Add the local pool to the external storage ptr.
pools
->
push_back
(
pool_
);
}
private:
/// Pointer to the created pool object.
isc
::
dhcp
::
Pool6Ptr
pool_
;
/// A storage for pool specific option values.
CfgOptionPtr
options_
;
isc
::
data
::
ConstElementPtr
user_context_
;
};
/// @brief Parser for a list of prefix delegation pools.
///
/// This parser iterates over a list of prefix delegation pool entries and
/// creates pool instances for each one. If the parsing is successful, the
/// collection of pools is committed to the provided storage.
class
PdPoolsListParser
:
public
PoolsListParser
{
public:
/// @brief Parse configuration entries.
///
/// This function parses configuration entries and creates instances
/// of prefix delegation pools .
///
/// @param storage is the pool storage in which to store the parsed
/// @param pd_pool_list pointer to an element that holds entries
/// that define a prefix delegation pool.
///
/// @throw DhcpConfigError if configuration parsing fails.
void
parse
(
PoolStoragePtr
pools
,
isc
::
data
::
ConstElementPtr
pd_pool_list
)
{
// Loop through the list of pd pools.
BOOST_FOREACH
(
ConstElementPtr
pd_pool
,
pd_pool_list
->
listValue
())
{
PdPoolParser
parser
;
parser
.
parse
(
pools
,
pd_pool
);
}
}
};
/// @anchor Subnet6ConfigParser
/// @brief This class parses a single IPv6 subnet.
///
/// This is the IPv6 derivation of the SubnetConfigParser class and it parses
/// the whole subnet definition. It creates parsersfor received configuration
/// parameters as needed.
class
Subnet6ConfigParser
:
public
SubnetConfigParser
{
public:
/// @brief Constructor
///
/// stores global scope parameters, options, option definitions.
Subnet6ConfigParser
()
:
SubnetConfigParser
(
AF_INET6
)
{
}
/// @brief Parses a single IPv6 subnet configuration and adds to the
/// Configuration Manager.
///
/// @param subnet A new subnet being configured.
/// @return a pointer to created Subnet6 object
Subnet6Ptr
parse
(
ConstElementPtr
subnet
)
{
/// Parse all pools first.
ConstElementPtr
pools
=
subnet
->
get
(
"pools"
);
if
(
pools
)
{
Pools6ListParser
parser
;
parser
.
parse
(
pools_
,
pools
);
}
ConstElementPtr
pd_pools
=
subnet
->
get
(
"pd-pools"
);
if
(
pd_pools
)
{
PdPoolsListParser
parser
;
parser
.
parse
(
pools_
,
pd_pools
);
}
SubnetPtr
generic
=
SubnetConfigParser
::
parse
(
subnet
);
if
(
!
generic
)
{
isc_throw
(
DhcpConfigError
,
"Failed to create an IPv6 subnet ("
<<
subnet
->
getPosition
()
<<
")"
);
}
Subnet6Ptr
sn6ptr
=
boost
::
dynamic_pointer_cast
<
Subnet6
>
(
subnet_
);
if
(
!
sn6ptr
)
{
// If we hit this, it is a programming error.
isc_throw
(
Unexpected
,
"Invalid Subnet6 cast in Subnet6ConfigParser::parse"
);
}
// Set relay information if it was provided
if
(
relay_info_
)
{
sn6ptr
->
setRelayInfo
(
*
relay_info_
);
}
// Parse Host Reservations for this subnet if any.
ConstElementPtr
reservations
=
subnet
->
get
(
"reservations"
);
if
(
reservations
)
{
HostCollection
hosts
;
HostReservationsListParser
<
HostReservationParser6
>
parser
;
parser
.
parse
(
subnet_
->
getID
(),
reservations
,
hosts
);
for
(
auto
h
=
hosts
.
begin
();
h
!=
hosts
.
end
();
++
h
)
{
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgHosts
()
->
add
(
*
h
);
}
}
return
(
sn6ptr
);
}
protected:
/// @brief Issues a DHCP6 server specific warning regarding duplicate subnet
/// options.
///
/// @param code is the numeric option code of the duplicate option
/// @param addr is the subnet address
/// @todo A means to know the correct logger and perhaps a common
/// message would allow this message to be emitted by the base class.
virtual
void
duplicate_option_warning
(
uint32_t
code
,
isc
::
asiolink
::
IOAddress
&
addr
)
{
LOG_WARN
(
dhcp6_logger
,
DHCP6_CONFIG_OPTION_DUPLICATE
)
.
arg
(
code
).
arg
(
addr
.
toText
());
}
/// @brief Instantiates the IPv6 Subnet based on a given IPv6 address
/// and prefix length.
///
/// @param addr is IPv6 prefix of the subnet.
/// @param len is the prefix length
void
initSubnet
(
isc
::
data
::
ConstElementPtr
params
,
isc
::
asiolink
::
IOAddress
addr
,
uint8_t
len
)
{
// Get all 'time' parameters using inheritance.
// If the subnet-specific value is defined then use it, else
// use the global value. The global value must always be
// present. If it is not, it is an internal error and exception
// is thrown.
Triplet
<
uint32_t
>
t1
=
getInteger
(
params
,
"renew-timer"
);
Triplet
<
uint32_t
>
t2
=
getInteger
(
params
,
"rebind-timer"
);
Triplet
<
uint32_t
>
pref
=
getInteger
(
params
,
"preferred-lifetime"
);
Triplet
<
uint32_t
>
valid
=
getInteger
(
params
,
"valid-lifetime"
);
// Subnet ID is optional. If it is not supplied the value of 0 is used,
// which means autogenerate. The value was inserted earlier by calling
// SimpleParser6::setAllDefaults.
SubnetID
subnet_id
=
static_cast
<
SubnetID
>
(
getInteger
(
params
,
"id"
));
// We want to log whether rapid-commit is enabled, so we get this
// before the actual subnet creation.
bool
rapid_commit
=
getBoolean
(
params
,
"rapid-commit"
);
std
::
ostringstream
output
;
output
<<
addr
<<
"/"
<<
static_cast
<
int
>
(
len
)
<<
" with params t1="
<<
t1
<<
", t2="
<<
t2
<<
", preferred-lifetime="
<<
pref
<<
", valid-lifetime="
<<
valid
<<
", rapid-commit is "
<<
(
rapid_commit
?
"enabled"
:
"disabled"
);
LOG_INFO
(
dhcp6_logger
,
DHCP6_CONFIG_NEW_SUBNET
).
arg
(
output
.
str
());
// Create a new subnet.
Subnet6
*
subnet6
=
new
Subnet6
(
addr
,
len
,
t1
,
t2
,
pref
,
valid
,
subnet_id
);
subnet_
.
reset
(
subnet6
);
// Enable or disable Rapid Commit option support for the subnet.
subnet6
->
setRapidCommit
(
rapid_commit
);
// Get interface-id option content. For now we support string
// representation only
std
::
string
ifaceid
=
getString
(
params
,
"interface-id"
);
std
::
string
iface
=
getString
(
params
,
"interface"
);
// Specifying both interface for locally reachable subnets and
// interface id for relays is mutually exclusive. Need to test for
// this condition.
if
(
!
ifaceid
.
empty
()
&&
!
iface
.
empty
())
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,