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
Sebastian Schrader
Kea
Commits
04cb6e8a
Commit
04cb6e8a
authored
Sep 23, 2014
by
Marcin Siodelski
Browse files
[3589] Option data configuration parsers store parsed data into cfgmgr.
parent
08c3a4ae
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/json_config_parser.cc
View file @
04cb6e8a
...
...
@@ -42,72 +42,6 @@ using namespace isc::asiolink;
namespace
{
/// @brief Parser for DHCP4 option data value.
///
/// This parser parses configuration entries that specify value of
/// a single option specific to DHCP4. It provides the DHCP4-specific
/// implementation of the abstract class OptionDataParser.
class
Dhcp4OptionDataParser
:
public
OptionDataParser
{
public:
/// @brief Constructor.
///
/// @param dummy first param, option names are always "Dhcp4/option-data[n]"
/// @param options is the option storage in which to store the parsed option
/// upon "commit".
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
Dhcp4OptionDataParser
(
const
std
::
string
&
,
OptionStoragePtr
options
,
ParserContextPtr
global_context
)
:
OptionDataParser
(
""
,
options
,
global_context
)
{
}
/// @brief static factory method for instantiating Dhcp4OptionDataParsers
///
/// @param param_name name of the parameter to be parsed.
/// @param options storage where the parameter value is to be stored.
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
/// @return returns a pointer to a new OptionDataParser. Caller is
/// is responsible for deleting it when it is no longer needed.
static
OptionDataParser
*
factory
(
const
std
::
string
&
param_name
,
OptionStoragePtr
options
,
ParserContextPtr
global_context
)
{
return
(
new
Dhcp4OptionDataParser
(
param_name
,
options
,
global_context
));
}
protected:
/// @brief Finds an option definition within the server's option space
///
/// Given an option space and an option code, find the correpsonding
/// option defintion within the server's option defintion storage.
///
/// @param option_space name of the parameter option space
/// @param option_code numeric value of the parameter to find
/// @return OptionDefintionPtr of the option defintion or an
/// empty OptionDefinitionPtr if not found.
/// @throw DhcpConfigError if the option space requested is not valid
/// for this server.
virtual
OptionDefinitionPtr
findServerSpaceOptionDefinition
(
std
::
string
&
option_space
,
uint32_t
option_code
)
{
OptionDefinitionPtr
def
;
if
(
option_space
==
"dhcp4"
&&
LibDHCP
::
isStandardOption
(
Option
::
V4
,
option_code
))
{
def
=
LibDHCP
::
getOptionDef
(
Option
::
V4
,
option_code
);
}
else
if
(
option_space
==
"dhcp6"
)
{
isc_throw
(
DhcpConfigError
,
"'dhcp6' option space name is reserved"
<<
" for DHCPv6 server"
);
}
else
{
// Check if this is a vendor-option. If it is, get vendor-specific
// definition.
uint32_t
vendor_id
=
CfgOption
::
optionSpaceToVendorId
(
option_space
);
if
(
vendor_id
)
{
def
=
LibDHCP
::
getVendorOptionDef
(
Option
::
V4
,
vendor_id
,
option_code
);
}
}
return
(
def
);
}
};
/// @brief Parser for IPv4 pool definitions.
///
/// This is the IPv4 derivation of the PoolParser class and handles pool
...
...
@@ -245,9 +179,7 @@ protected:
}
else
if
(
config_id
.
compare
(
"relay"
)
==
0
)
{
parser
=
new
RelayInfoParser
(
config_id
,
relay_info_
,
Option
::
V4
);
}
else
if
(
config_id
.
compare
(
"option-data"
)
==
0
)
{
parser
=
new
OptionDataListParser
(
config_id
,
options_
,
global_context_
,
Dhcp4OptionDataParser
::
factory
);
parser
=
new
OptionDataListParser
(
config_id
,
options_
,
AF_INET
);
}
else
{
isc_throw
(
NotImplemented
,
"unsupported parameter: "
<<
config_id
);
}
...
...
@@ -448,10 +380,7 @@ namespace dhcp {
}
else
if
(
config_id
.
compare
(
"subnet4"
)
==
0
)
{
parser
=
new
Subnets4ListConfigParser
(
config_id
);
}
else
if
(
config_id
.
compare
(
"option-data"
)
==
0
)
{
parser
=
new
OptionDataListParser
(
config_id
,
globalContext
()
->
options_
,
globalContext
(),
Dhcp4OptionDataParser
::
factory
);
parser
=
new
OptionDataListParser
(
config_id
,
CfgOptionPtr
(),
AF_INET
);
}
else
if
(
config_id
.
compare
(
"option-def"
)
==
0
)
{
parser
=
new
OptionDefListParser
(
config_id
,
globalContext
());
}
else
if
((
config_id
.
compare
(
"version"
)
==
0
)
||
...
...
src/bin/dhcp6/json_config_parser.cc
View file @
04cb6e8a
...
...
@@ -56,73 +56,6 @@ typedef boost::shared_ptr<BooleanParser> BooleanParserPtr;
typedef
boost
::
shared_ptr
<
StringParser
>
StringParserPtr
;
typedef
boost
::
shared_ptr
<
Uint32Parser
>
Uint32ParserPtr
;
/// @brief Parser for DHCP6 option data value.
///
/// This parser parses configuration entries that specify value of
/// a single option specific to DHCP6. It provides the DHCP6-specific
/// implementation of the abstract class OptionDataParser.
class
Dhcp6OptionDataParser
:
public
OptionDataParser
{
public:
/// @brief Constructor.
///
/// @param dummy first param, option names are always "Dhcp6/option-data[n]"
/// @param options is the option storage in which to store the parsed option
/// upon "commit".
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
Dhcp6OptionDataParser
(
const
std
::
string
&
,
OptionStoragePtr
options
,
ParserContextPtr
global_context
)
:
OptionDataParser
(
""
,
options
,
global_context
)
{
}
/// @brief static factory method for instantiating Dhcp4OptionDataParsers
///
/// @param param_name name of the parameter to be parsed.
/// @param options storage where the parameter value is to be stored.
/// @param global_context is a pointer to the global context which
/// stores global scope parameters, options, option defintions.
/// @return returns a pointer to a new OptionDataParser. Caller is
/// is responsible for deleting it when it is no longer needed.
static
OptionDataParser
*
factory
(
const
std
::
string
&
param_name
,
OptionStoragePtr
options
,
ParserContextPtr
global_context
)
{
return
(
new
Dhcp6OptionDataParser
(
param_name
,
options
,
global_context
));
}
protected:
/// @brief Finds an option definition within the server's option space
///
/// Given an option space and an option code, find the correpsonding
/// option defintion within the server's option defintion storage.
///
/// @param option_space name of the parameter option space
/// @param option_code numeric value of the parameter to find
/// @return OptionDefintionPtr of the option defintion or an
/// empty OptionDefinitionPtr if not found.
/// @throw DhcpConfigError if the option space requested is not valid
/// for this server.
virtual
OptionDefinitionPtr
findServerSpaceOptionDefinition
(
std
::
string
&
option_space
,
uint32_t
option_code
)
{
OptionDefinitionPtr
def
;
if
(
option_space
==
"dhcp6"
&&
LibDHCP
::
isStandardOption
(
Option
::
V6
,
option_code
))
{
def
=
LibDHCP
::
getOptionDef
(
Option
::
V6
,
option_code
);
}
else
if
(
option_space
==
"dhcp4"
)
{
isc_throw
(
DhcpConfigError
,
"'dhcp4' option space name is reserved"
<<
" for DHCPv4 server"
);
}
else
{
// Check if this is a vendor-option. If it is, get vendor-specific
// definition.
uint32_t
vendor_id
=
CfgOption
::
optionSpaceToVendorId
(
option_space
);
if
(
vendor_id
)
{
def
=
LibDHCP
::
getVendorOptionDef
(
Option
::
V6
,
vendor_id
,
option_code
);
}
}
return
(
def
);
}
};
/// @brief Parser for IPv6 pool definitions.
///
/// This is the IPv6 derivation of the PoolParser class and handles pool
...
...
@@ -456,9 +389,7 @@ protected:
}
else
if
(
config_id
.
compare
(
"pd-pools"
)
==
0
)
{
parser
=
new
PdPoolListParser
(
config_id
,
pools_
);
}
else
if
(
config_id
.
compare
(
"option-data"
)
==
0
)
{
parser
=
new
OptionDataListParser
(
config_id
,
options_
,
global_context_
,
Dhcp6OptionDataParser
::
factory
);
parser
=
new
OptionDataListParser
(
config_id
,
options_
,
AF_INET6
);
}
else
{
isc_throw
(
NotImplemented
,
"unsupported parameter: "
<<
config_id
);
}
...
...
@@ -667,10 +598,7 @@ namespace dhcp {
}
else
if
(
config_id
.
compare
(
"subnet6"
)
==
0
)
{
parser
=
new
Subnets6ListConfigParser
(
config_id
);
}
else
if
(
config_id
.
compare
(
"option-data"
)
==
0
)
{
parser
=
new
OptionDataListParser
(
config_id
,
globalContext
()
->
options_
,
globalContext
(),
Dhcp6OptionDataParser
::
factory
);
parser
=
new
OptionDataListParser
(
config_id
,
CfgOptionPtr
(),
AF_INET6
);
}
else
if
(
config_id
.
compare
(
"option-def"
)
==
0
)
{
parser
=
new
OptionDefListParser
(
config_id
,
globalContext
());
}
else
if
(
config_id
.
compare
(
"version"
)
==
0
)
{
...
...
src/bin/dhcp6/tests/config_parser_unittest.cc
View file @
04cb6e8a
...
...
@@ -2741,7 +2741,11 @@ TEST_F(Dhcp6ParserTest, vendorOptionsCsv) {
// The goal of this test is to verify that the standard option can
// be configured to encapsulate multiple other options.
TEST_F
(
Dhcp6ParserTest
,
stdOptionDataEncapsulate
)
{
/// @todo This test is currently disabled because it relies on the option
/// 17 which is treated differently than all other options. There are no
/// other standard options used by Kea which would encapsulate other
/// options and for which values could be configured here.
TEST_F
(
Dhcp6ParserTest
,
DISABLED_stdOptionDataEncapsulate
)
{
// The configuration is two stage process in this test.
// In the first stahe we create definitions of suboptions
...
...
src/lib/dhcpsrv/cfg_option.cc
View file @
04cb6e8a
...
...
@@ -69,6 +69,33 @@ CfgOption::copy(CfgOption& other) const {
other
=
new_cfg
;
}
void
CfgOption
::
encapsulate
()
{
// Append sub-options to the top level "dhcp4" option space.
encapsulateInternal
(
DHCP4_OPTION_SPACE
);
// Append sub-options to the top level "dhcp6" option space.
encapsulateInternal
(
DHCP6_OPTION_SPACE
);
}
void
CfgOption
::
encapsulateInternal
(
const
std
::
string
&
option_space
)
{
OptionContainerPtr
options
=
getAll
(
option_space
);
for
(
OptionContainer
::
const_iterator
opt
=
options
->
begin
();
opt
!=
options
->
end
();
++
opt
)
{
const
std
::
string
&
encap_space
=
opt
->
option
->
getEncapsulatedSpace
();
if
(
!
encap_space
.
empty
())
{
OptionContainerPtr
encap_options
=
getAll
(
encap_space
);
for
(
OptionContainer
::
const_iterator
encap_opt
=
encap_options
->
begin
();
encap_opt
!=
encap_options
->
end
();
++
encap_opt
)
{
if
(
!
opt
->
option
->
getOption
(
encap_opt
->
option
->
getType
()))
{
opt
->
option
->
addOption
(
encap_opt
->
option
);
}
}
}
}
}
template
<
typename
Selector
>
void
CfgOption
::
mergeInternal
(
const
OptionSpaceContainer
<
OptionContainer
,
...
...
src/lib/dhcpsrv/cfg_option.h
View file @
04cb6e8a
...
...
@@ -269,6 +269,14 @@ public:
/// @param [out] other An object to copy the configuration to.
void
copy
(
CfgOption
&
other
)
const
;
/// @brief Appends encapsulated options to top-level options.
///
/// This method iterates over the top-level options (from "dhcp4"
/// and "dhcp6" option space) and checks which option spaces these
/// options encapsulate. For each encapsulated option space, the
/// options from this option space are appended to top-level options.
void
encapsulate
();
/// @brief Returns all options for the specified option space.
///
/// This method will not return vendor options, i.e. having option space
...
...
@@ -332,6 +340,12 @@ public:
private:
/// @brief Appends encapsulated options to the options in an option space.
///
/// @param option_space Name of the option space containing optionn to
/// which encapsulated options are appended.
void
encapsulateInternal
(
const
std
::
string
&
option_space
);
/// @brief Merges data from two option containers.
///
/// This method merges options from one option container to another
...
...
src/lib/dhcpsrv/dhcp_parsers.cc
View file @
04cb6e8a
...
...
@@ -43,7 +43,6 @@ ParserContext::ParserContext(Option::Universe universe):
boolean_values_
(
new
BooleanStorage
()),
uint32_values_
(
new
Uint32Storage
()),
string_values_
(
new
StringStorage
()),
options_
(
new
OptionStorage
()),
hooks_libraries_
(),
universe_
(
universe
)
{
...
...
@@ -53,7 +52,6 @@ ParserContext::ParserContext(const ParserContext& rhs):
boolean_values_
(),
uint32_values_
(),
string_values_
(),
options_
(),
hooks_libraries_
(),
universe_
(
rhs
.
universe_
)
{
...
...
@@ -77,7 +75,6 @@ ParserContext::copyContext(const ParserContext& ctx) {
copyContextPointer
(
ctx
.
boolean_values_
,
boolean_values_
);
copyContextPointer
(
ctx
.
uint32_values_
,
uint32_values_
);
copyContextPointer
(
ctx
.
string_values_
,
string_values_
);
copyContextPointer
(
ctx
.
options_
,
options_
);
copyContextPointer
(
ctx
.
hooks_libraries_
,
hooks_libraries_
);
// Copy universe.
universe_
=
ctx
.
universe_
;
...
...
@@ -281,20 +278,16 @@ HooksLibrariesParser::getLibraries(std::vector<std::string>& libraries,
}
// **************************** OptionDataParser *************************
OptionDataParser
::
OptionDataParser
(
const
std
::
string
&
,
OptionStoragePtr
options
,
ParserContextPtr
global_context
)
OptionDataParser
::
OptionDataParser
(
const
std
::
string
&
,
const
CfgOptionPtr
&
cfg
,
const
uint16_t
address_family
)
:
boolean_values_
(
new
BooleanStorage
()),
string_values_
(
new
StringStorage
()),
uint32_values_
(
new
Uint32Storage
()),
options_
(
options
),
option_descriptor_
(
false
),
global_context_
(
global_context
)
{
if
(
!
options_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"parser logic error: "
<<
"options storage may not be NULL"
);
}
if
(
!
global_context_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"parser logic error: "
<<
"context may may not be NULL"
);
string_values_
(
new
StringStorage
()),
uint32_values_
(
new
Uint32Storage
()),
option_descriptor_
(
false
),
cfg_
(
cfg
),
address_family_
(
address_family
)
{
// If configuration not specified, then it is a global configuration
// scope.
if
(
!
cfg_
)
{
cfg_
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOption
();
}
}
...
...
@@ -333,39 +326,57 @@ OptionDataParser::build(ConstElementPtr option_data_entries) {
// Try to create the option instance.
createOption
(
option_data_entries
);
}
void
OptionDataParser
::
commit
()
{
if
(
!
option_descriptor_
.
option
)
{
// Before we can commit the new option should be configured. If it is
// not than somebody must have called commit() before build().
isc_throw
(
isc
::
InvalidOperation
,
"parser logic error: no option has been configured and"
" thus there is nothing to commit. Has build() been called?"
);
}
uint16_t
opt_type
=
option_descriptor_
.
option
->
getType
();
OptionContainerPtr
options
=
options_
->
getItems
(
option_space_
);
// The getItems() should never return NULL pointer. If there are no
// options configured for the particular option space a pointer
// to an empty container should be returned.
assert
(
options
);
OptionContainerTypeIndex
&
idx
=
options
->
get
<
1
>
();
// Try to find options with the particular option code in the main
// storage. If found, remove these options because they will be
// replaced with new one.
OptionContainerTypeRange
range
=
idx
.
equal_range
(
opt_type
);
if
(
std
::
distance
(
range
.
first
,
range
.
second
)
>
0
)
{
idx
.
erase
(
range
.
first
,
range
.
second
);
cfg_
->
add
(
option_descriptor_
.
option
,
option_descriptor_
.
persistent
,
option_space_
);
}
void
OptionDataParser
::
commit
()
{
// Does nothing
}
OptionDefinitionPtr
OptionDataParser
::
findServerSpaceOptionDefinition
(
const
std
::
string
&
option_space
,
const
uint32_t
option_code
)
const
{
const
Option
::
Universe
u
=
address_family_
==
AF_INET
?
Option
::
V4
:
Option
::
V6
;
if
((
option_space
==
DHCP4_OPTION_SPACE
)
&&
(
u
==
Option
::
V6
))
{
isc_throw
(
DhcpConfigError
,
"'"
<<
DHCP4_OPTION_SPACE
<<
"' option space name is reserved for DHCPv4 server"
);
}
else
if
((
option_space
==
DHCP6_OPTION_SPACE
)
&&
(
u
==
Option
::
V4
))
{
isc_throw
(
DhcpConfigError
,
"'"
<<
DHCP6_OPTION_SPACE
<<
"' option space name is reserved for DHCPv6 server"
);
}
// Append new option to the main storage.
options_
->
addItem
(
option_descriptor_
,
option_space_
);
OptionDefinitionPtr
def
;
if
(((
option_space
==
DHCP4_OPTION_SPACE
)
||
(
option_space
==
DHCP6_OPTION_SPACE
))
&&
LibDHCP
::
isStandardOption
(
u
,
option_code
))
{
def
=
LibDHCP
::
getOptionDef
(
u
,
option_code
);
}
else
{
// Check if this is a vendor-option. If it is, get vendor-specific
// definition.
uint32_t
vendor_id
=
CfgOption
::
optionSpaceToVendorId
(
option_space
);
if
(
vendor_id
)
{
def
=
LibDHCP
::
getVendorOptionDef
(
u
,
vendor_id
,
option_code
);
}
}
return
(
def
);
}
void
OptionDataParser
::
createOption
(
ConstElementPtr
option_data
)
{
const
Option
::
Universe
universe
=
address_family_
==
AF_INET
?
Option
::
V4
:
Option
::
V6
;
// Check if mandatory parameters are specified.
uint32_t
code
;
std
::
string
name
;
...
...
@@ -379,8 +390,8 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
ex
.
what
()
<<
"("
<<
option_data
->
getPosition
()
<<
")"
);
}
// Check parameters having default values.
std
::
string
space
=
string_values_
->
getOptionalParam
(
"space"
,
global_context_
->
universe_
==
Option
::
V4
?
"dhcp4"
:
"dhcp6"
);
std
::
string
space
=
string_values_
->
getOptionalParam
(
"space"
,
universe
==
Option
::
V4
?
"dhcp4"
:
"dhcp6"
);
bool
csv_format
=
boolean_values_
->
getOptionalParam
(
"csv-format"
,
false
);
// Option code is held in the uint32_t storage but is supposed to
...
...
@@ -391,14 +402,14 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
isc_throw
(
DhcpConfigError
,
"option code must not be zero "
"("
<<
uint32_values_
->
getPosition
(
"code"
)
<<
")"
);
}
else
if
(
global_context_
->
universe
_
==
Option
::
V4
&&
}
else
if
(
universe
==
Option
::
V4
&&
code
>
std
::
numeric_limits
<
uint8_t
>::
max
())
{
isc_throw
(
DhcpConfigError
,
"invalid option code '"
<<
code
<<
"', it must not exceed '"
<<
static_cast
<
int
>
(
std
::
numeric_limits
<
uint8_t
>::
max
())
<<
"' ("
<<
uint32_values_
->
getPosition
(
"code"
)
<<
")"
);
}
else
if
(
global_context_
->
universe
_
==
Option
::
V6
&&
}
else
if
(
universe
==
Option
::
V6
&&
code
>
std
::
numeric_limits
<
uint16_t
>::
max
())
{
isc_throw
(
DhcpConfigError
,
"invalid option code '"
<<
code
<<
"', it must not exceed '"
...
...
@@ -443,18 +454,7 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
// need to search for its definition among user-configured
// options. They are expected to be in the global storage
// already.
OptionDefContainerPtr
defs
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOptionDef
()
->
getAll
(
space
);
// The getItems() should never return the NULL pointer. If there are
// no option definitions for the particular option space a pointer
// to an empty container should be returned.
assert
(
defs
);
const
OptionDefContainerTypeIndex
&
idx
=
defs
->
get
<
1
>
();
OptionDefContainerTypeRange
range
=
idx
.
equal_range
(
code
);
if
(
std
::
distance
(
range
.
first
,
range
.
second
)
>
0
)
{
def
=
*
range
.
first
;
}
def
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOptionDef
()
->
get
(
space
,
code
);
// It's ok if we don't have option format if the option is
// specified as hex
...
...
@@ -510,8 +510,8 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
// for all options. Consequently an error will be issued if an option
// definition does not exist for a particular option code. For now it is
// ok to create generic option if definition does not exist.
OptionPtr
option
(
new
Option
(
global_context_
->
universe
_
,
static_cast
<
uint16_t
>
(
code
),
binary
));
OptionPtr
option
(
new
Option
(
universe
,
static_cast
<
uint16_t
>
(
code
),
binary
));
// The created option is stored in option_descriptor_ class member
// until the commit stage when it is inserted into the main storage.
// If an option with the same code exists in main storage already the
...
...
@@ -537,13 +537,12 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
// an instance of our option.
try
{
OptionPtr
option
=
csv_format
?
def
->
optionFactory
(
global_context_
->
universe_
,
code
,
data_tokens
)
:
def
->
optionFactory
(
global_context_
->
universe_
,
code
,
binary
);
def
->
optionFactory
(
universe
,
code
,
data_tokens
)
:
def
->
optionFactory
(
universe
,
code
,
binary
);
OptionDescriptor
desc
(
option
,
false
);
option_descriptor_
.
option
=
option
;
option_descriptor_
.
persistent
=
false
;
}
catch
(
const
isc
::
Exception
&
ex
)
{
isc_throw
(
DhcpConfigError
,
"option data does not match"
<<
" option definition (space: "
<<
space
...
...
@@ -559,39 +558,18 @@ OptionDataParser::createOption(ConstElementPtr option_data) {
// **************************** OptionDataListParser *************************
OptionDataListParser
::
OptionDataListParser
(
const
std
::
string
&
,
OptionStoragePtr
options
,
ParserContextPtr
global_context
,
OptionDataParserFactory
*
optionDataParserFactory
)
:
options_
(
options
),
local_options_
(
new
OptionStorage
()),
global_context_
(
global_context
),
optionDataParserFactory_
(
optionDataParserFactory
)
{
if
(
!
options_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"parser logic error: "
<<
"options storage may not be NULL"
);
}
if
(
!
options_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"parser logic error: "
<<
"context may not be NULL"
);
}
if
(
!
optionDataParserFactory_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"parser logic error: "
<<
"option data parser factory may not be NULL"
);
}
const
CfgOptionPtr
&
cfg
,
const
uint16_t
address_family
)
:
cfg_
(
cfg
),
address_family_
(
address_family
)
{
}
void
OptionDataListParser
::
build
(
ConstElementPtr
option_data_list
)
{
BOOST_FOREACH
(
ConstElementPtr
option_value
,
option_data_list
->
listValue
())
{
boost
::
shared_ptr
<
OptionDataParser
>
parser
((
*
optionDataParserFactory_
)(
"option-data"
,
local_options_
,
global_context_
));
parser
(
new
OptionDataParser
(
"option-data"
,
cfg_
,
address_family_
));
// options_ member will hold instances of all options thus
// each OptionDataParser takes it as a storage.
// Build the instance of a single option.
parser
->
build
(
option_value
);
// Store a parser as it will be used to commit.
parsers_
.
push_back
(
parser
);
}
}
...
...
@@ -601,11 +579,6 @@ OptionDataListParser::commit() {
BOOST_FOREACH
(
ParserPtr
parser
,
parsers_
)
{
parser
->
commit
();
}
// Parsing was successful and we have all configured
// options in local storage. We can now replace old values
// with new values.
std
::
swap
(
*
local_options_
,
*
options_
);
}
// ******************************** OptionDefParser ****************************
...
...
@@ -977,15 +950,16 @@ SubnetConfigParser::SubnetConfigParser(const std::string&,
ParserContextPtr
global_context
,
const
isc
::
asiolink
::
IOAddress
&
default_addr
)
:
uint32_values_
(
new
Uint32Storage
()),
string_values_
(
new
StringStorage
()),
pools_
(
new
PoolStorage
()),
options_
(
new
OptionStorage
()
),
global_context_
(
global_context
),
relay_info_
(
new
isc
::
dhcp
::
Subnet
::
RelayInfo
(
default_addr
))
{
pools_
(
new
PoolStorage
()),
global_context_
(
global_context
),
relay_info_
(
new
isc
::
dhcp
::
Subnet
::
RelayInfo
(
default_addr
)
),
options_
(
new
CfgOption
(
))
{
// The first parameter should always be "subnet", but we don't check
// against that here in case some wants to reuse this parser somewhere.
if
(
!
global_context_
)
{
isc_throw
(
isc
::
dhcp
::
DhcpConfigError
,
"parser logic error: "
<<
"context storage may not be NULL"
);
}
}
void
...
...
@@ -1027,61 +1001,6 @@ SubnetConfigParser::build(ConstElementPtr subnet) {
}
}
void
SubnetConfigParser
::
appendSubOptions
(
const
std
::
string
&
option_space
,
OptionPtr
&
option
)
{
// Only non-NULL options are stored in option container.
// If this option pointer is NULL this is a serious error.
assert
(
option
);
OptionDefinitionPtr
def
;
if
(
isServerStdOption
(
option_space
,
option
->
getType
()))
{
def
=
getServerStdOptionDefinition
(
option
->
getType
());
// Definitions for some of the standard options hasn't been
// implemented so it is ok to leave here.
if
(
!
def
)
{
return
;
}
}
else
{
OptionDefContainerPtr
defs
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOptionDef
()
->
getAll
(
option_space
);
const
OptionDefContainerTypeIndex
&
idx
=
defs
->
get
<
1
>
();
const
OptionDefContainerTypeRange
&
range
=
idx
.
equal_range
(
option
->
getType
());
// There is no definition so we have to leave.
if
(
std
::
distance
(
range
.
first
,
range
.
second
)
==
0
)
{
return
;
}
def
=
*
range
.
first
;
// If the definition exists, it must be non-NULL.
// Otherwise it is a programming error.
assert
(
def
);
}
// We need to get option definition for the particular option space
// and code. This definition holds the information whether our
// option encapsulates any option space.
// Get the encapsulated option space name.
std
::
string
encapsulated_space
=
def
->
getEncapsulatedSpace
();
// If option space name is empty it means that our option does not
// encapsulate any option space (does not include sub-options).
if
(
!
encapsulated_space
.
empty
())
{
// Get the sub-options that belong to the encapsulated
// option space.
const
OptionContainerPtr
sub_opts
=
global_context_
->
options_
->
getItems
(
encapsulated_space
);
// Append sub-options to the option.
BOOST_FOREACH
(
OptionDescriptor
desc
,
*
sub_opts
)
{
if
(
desc
.
option
)
{
option
->
addOption
(
desc
.
option
);
}
}
}
}
void
SubnetConfigParser
::
createSubnet
()
{
std
::
string