mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-03 15:35:17 +00:00
[#1245] Checkpoint: flatten v4
This commit is contained in:
@@ -335,10 +335,8 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
// Rollback informs whether error occurred and original data
|
// Rollback informs whether error occurred and original data
|
||||||
// have to be restored to global storages.
|
// have to be restored to global storages.
|
||||||
bool rollback = false;
|
bool rollback = false;
|
||||||
// config_pair holds the details of the current parser when iterating over
|
// Global parameter name in case of an error.
|
||||||
// the parsers. It is declared outside the loops so in case of an error,
|
string parameter_name;
|
||||||
// the name of the failing parser can be retrieved in the "catch" clause.
|
|
||||||
ConfigPair config_pair;
|
|
||||||
ElementPtr mutable_cfg;
|
ElementPtr mutable_cfg;
|
||||||
SrvConfigPtr srv_cfg;
|
SrvConfigPtr srv_cfg;
|
||||||
try {
|
try {
|
||||||
@@ -362,188 +360,229 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
// And now derive (inherit) global parameters to subnets, if not specified.
|
// And now derive (inherit) global parameters to subnets, if not specified.
|
||||||
SimpleParser4::deriveParameters(mutable_cfg);
|
SimpleParser4::deriveParameters(mutable_cfg);
|
||||||
|
|
||||||
|
// In principle we could have the following code structured as a series
|
||||||
|
// of long if else if clauses. That would give a marginal performance
|
||||||
|
// boost, but would make the code less readable. We had serious issues
|
||||||
|
// with the parser code debugability, so I decided to keep it as a
|
||||||
|
// series of independent ifs.
|
||||||
|
|
||||||
// We need definitions first
|
// We need definitions first
|
||||||
ConstElementPtr option_defs = mutable_cfg->get("option-def");
|
ConstElementPtr option_defs = mutable_cfg->get("option-def");
|
||||||
if (option_defs) {
|
if (option_defs) {
|
||||||
|
parameter_name = "option-def";
|
||||||
OptionDefListParser parser(AF_INET);
|
OptionDefListParser parser(AF_INET);
|
||||||
CfgOptionDefPtr cfg_option_def = srv_cfg->getCfgOptionDef();
|
CfgOptionDefPtr cfg_option_def = srv_cfg->getCfgOptionDef();
|
||||||
parser.parse(cfg_option_def, option_defs);
|
parser.parse(cfg_option_def, option_defs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This parser is used in several places, so it should be available
|
ConstElementPtr option_datas = mutable_cfg->get("option-data");
|
||||||
// early.
|
if (option_datas) {
|
||||||
Dhcp4ConfigParser global_parser;
|
parameter_name = "option-data";
|
||||||
|
OptionDataListParser parser(AF_INET);
|
||||||
|
CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
|
||||||
|
parser.parse(cfg_option, option_datas);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr control_socket = mutable_cfg->get("control-socket");
|
||||||
|
if (control_socket) {
|
||||||
|
parameter_name = "control-socket";
|
||||||
|
ControlSocketParser parser;
|
||||||
|
parser.parse(*srv_cfg, control_socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
|
||||||
|
if (multi_threading) {
|
||||||
|
parameter_name = "multi-threading";
|
||||||
|
MultiThreadingConfigParser parser;
|
||||||
|
parser.parse(*srv_cfg, multi_threading);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr queue_control = mutable_cfg->get("dhcp-queue-control");
|
||||||
|
if (queue_control) {
|
||||||
|
parameter_name = "dhcp-queue-control";
|
||||||
|
DHCPQueueControlParser parser;
|
||||||
|
srv_cfg->setDHCPQueueControl(parser.parse(queue_control));
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr hr_identifiers =
|
||||||
|
mutable_cfg->get("host-reservation-identifiers");
|
||||||
|
if (hr_identifiers) {
|
||||||
|
parameter_name = "host-reservation-identifiers";
|
||||||
|
HostReservationIdsParser4 parser;
|
||||||
|
parser.parse(hr_identifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr ifaces_config = mutable_cfg->get("interfaces-config");
|
||||||
|
if (ifaces_config) {
|
||||||
|
parameter_name = "interfaces-config";
|
||||||
|
ElementPtr mutable_cfg =
|
||||||
|
boost::const_pointer_cast<Element>(ifaces_config);
|
||||||
|
if (check_only) {
|
||||||
|
// No re-detection in check only mode
|
||||||
|
mutable_cfg->set("re-detect", Element::create(false));
|
||||||
|
}
|
||||||
|
IfacesConfigParser parser(AF_INET);
|
||||||
|
CfgIfacePtr cfg_iface = srv_cfg->getCfgIface();
|
||||||
|
parser.parse(cfg_iface, ifaces_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr sanity_checks = mutable_cfg->get("sanity-checks");
|
||||||
|
if (sanity_checks) {
|
||||||
|
parameter_name = "sanity-checks";
|
||||||
|
SanityChecksParser parser;
|
||||||
|
parser.parse(*srv_cfg, sanity_checks);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr expiration_cfg =
|
||||||
|
mutable_cfg->get("expired-leases-processing");
|
||||||
|
if (expiration_cfg) {
|
||||||
|
parameter_name = "expired-leases-processing";
|
||||||
|
ExpirationConfigParser parser;
|
||||||
|
parser.parse(expiration_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The hooks-libraries configuration must be parsed after parsing
|
||||||
|
// multi-threading configuration so that libraries are checked
|
||||||
|
// for multi-threading compatibility.
|
||||||
|
ConstElementPtr hooks_libraries = mutable_cfg->get("hooks-libraries");
|
||||||
|
if (hooks_libraries) {
|
||||||
|
parameter_name = "hooks-libraries";
|
||||||
|
HooksLibrariesParser hooks_parser;
|
||||||
|
HooksConfig& libraries = srv_cfg->getHooksConfig();
|
||||||
|
hooks_parser.parse(libraries, hooks_libraries);
|
||||||
|
libraries.verifyLibraries(hooks_libraries->getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
// D2 client configuration.
|
// D2 client configuration.
|
||||||
D2ClientConfigPtr d2_client_cfg;
|
D2ClientConfigPtr d2_client_cfg;
|
||||||
|
|
||||||
|
// Legacy DhcpConfigParser stuff below.
|
||||||
|
ConstElementPtr dhcp_ddns = mutable_cfg->get("dhcp-ddns");
|
||||||
|
if (dhcp_ddns) {
|
||||||
|
parameter_name = "dhcp-ddns";
|
||||||
|
// Apply defaults
|
||||||
|
D2ClientConfigParser::setAllDefaults(dhcp_ddns);
|
||||||
|
D2ClientConfigParser parser;
|
||||||
|
d2_client_cfg = parser.parse(dhcp_ddns);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr client_classes = mutable_cfg->get("client-classes");
|
||||||
|
if (client_classes) {
|
||||||
|
parameter_name = "client-classes";
|
||||||
|
ClientClassDefListParser parser;
|
||||||
|
ClientClassDictionaryPtr dictionary =
|
||||||
|
parser.parse(client_classes, AF_INET);
|
||||||
|
srv_cfg->setClientClassDictionary(dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Please move at the end when migration will be finished.
|
||||||
|
ConstElementPtr lease_database = mutable_cfg->get("lease-database");
|
||||||
|
if (lease_database) {
|
||||||
|
parameter_name = "lease-database";
|
||||||
|
db::DbAccessParser parser;
|
||||||
|
std::string access_string;
|
||||||
|
parser.parse(access_string, lease_database);
|
||||||
|
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
||||||
|
cfg_db_access->setLeaseDbAccessString(access_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr hosts_database = mutable_cfg->get("hosts-database");
|
||||||
|
if (hosts_database) {
|
||||||
|
parameter_name = "hosts-database";
|
||||||
|
db::DbAccessParser parser;
|
||||||
|
std::string access_string;
|
||||||
|
parser.parse(access_string, hosts_database);
|
||||||
|
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
||||||
|
cfg_db_access->setHostDbAccessString(access_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr hosts_databases = mutable_cfg->get("hosts-databases");
|
||||||
|
if (hosts_databases) {
|
||||||
|
parameter_name = "hosts-databases";
|
||||||
|
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
||||||
|
db::DbAccessParser parser;
|
||||||
|
for (auto it : hosts_databases->listValue()) {
|
||||||
|
std::string access_string;
|
||||||
|
parser.parse(access_string, it);
|
||||||
|
cfg_db_access->setHostDbAccessString(access_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr subnet4 = mutable_cfg->get("subnet4");
|
||||||
|
if (subnet4) {
|
||||||
|
parameter_name = "subnet4";
|
||||||
|
Subnets4ListConfigParser subnets_parser;
|
||||||
|
// parse() returns number of subnets parsed. We may log it one day.
|
||||||
|
subnets_parser.parse(srv_cfg, subnet4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This parser is used in several places.
|
||||||
|
Dhcp4ConfigParser global_parser;
|
||||||
|
|
||||||
|
ConstElementPtr shared_networks = mutable_cfg->get("shared-networks");
|
||||||
|
if (shared_networks) {
|
||||||
|
parameter_name = "shared-networks";
|
||||||
|
/// We need to create instance of SharedNetworks4ListParser
|
||||||
|
/// and parse the list of the shared networks into the
|
||||||
|
/// CfgSharedNetworks4 object. One additional step is then to
|
||||||
|
/// add subnets from the CfgSharedNetworks4 into CfgSubnets4
|
||||||
|
/// as well.
|
||||||
|
SharedNetworks4ListParser parser;
|
||||||
|
CfgSharedNetworks4Ptr cfg = srv_cfg->getCfgSharedNetworks4();
|
||||||
|
parser.parse(cfg, shared_networks);
|
||||||
|
|
||||||
|
// We also need to put the subnets it contains into normal
|
||||||
|
// subnets list.
|
||||||
|
global_parser.copySubnets4(srv_cfg->getCfgSubnets4(), cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr reservations = mutable_cfg->get("reservations");
|
||||||
|
if (reservations) {
|
||||||
|
parameter_name = "reservations";
|
||||||
|
HostCollection hosts;
|
||||||
|
HostReservationsListParser<HostReservationParser4> parser;
|
||||||
|
parser.parse(SUBNET_ID_GLOBAL, reservations, hosts);
|
||||||
|
for (auto h = hosts.begin(); h != hosts.end(); ++h) {
|
||||||
|
srv_cfg->getCfgHosts()->add(*h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstElementPtr config_control = mutable_cfg->get("config-control");
|
||||||
|
if (config_control) {
|
||||||
|
parameter_name = "config-control";
|
||||||
|
ConfigControlParser parser;
|
||||||
|
ConfigControlInfoPtr config_ctl_info = parser.parse(config_control);
|
||||||
|
CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
|
||||||
|
}
|
||||||
|
|
||||||
// Make parsers grouping.
|
// Make parsers grouping.
|
||||||
|
ConfigPair config_pair;
|
||||||
const std::map<std::string, ConstElementPtr>& values_map =
|
const std::map<std::string, ConstElementPtr>& values_map =
|
||||||
mutable_cfg->mapValue();
|
mutable_cfg->mapValue();
|
||||||
BOOST_FOREACH(config_pair, values_map) {
|
BOOST_FOREACH(config_pair, values_map) {
|
||||||
// In principle we could have the following code structured as a series
|
|
||||||
// of long if else if clauses. That would give a marginal performance
|
|
||||||
// boost, but would make the code less readable. We had serious issues
|
|
||||||
// with the parser code debugability, so I decided to keep it as a
|
|
||||||
// series of independent ifs.
|
|
||||||
if (config_pair.first == "option-def") {
|
|
||||||
// This is converted to SimpleParser and is handled already above.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "option-data") {
|
parameter_name = config_pair.first;
|
||||||
OptionDataListParser parser(AF_INET);
|
|
||||||
CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
|
|
||||||
parser.parse(cfg_option, config_pair.second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "control-socket") {
|
// These are converted to SimpleParser and are handled already above.
|
||||||
ControlSocketParser parser;
|
if ((config_pair.first == "option-def") ||
|
||||||
parser.parse(*srv_cfg, config_pair.second);
|
(config_pair.first == "option-data") ||
|
||||||
continue;
|
(config_pair.first == "control-socket") ||
|
||||||
}
|
(config_pair.first == "multi-threading") ||
|
||||||
|
(config_pair.first == "dhcp-queue-control") ||
|
||||||
if (config_pair.first == "multi-threading") {
|
(config_pair.first == "host-reservation-identifiers") ||
|
||||||
MultiThreadingConfigParser parser;
|
(config_pair.first == "interfaces-config") ||
|
||||||
parser.parse(*srv_cfg, config_pair.second);
|
(config_pair.first == "sanity-checks") ||
|
||||||
continue;
|
(config_pair.first == "expired-leases-processing") ||
|
||||||
}
|
(config_pair.first == "hooks-libraries") ||
|
||||||
|
(config_pair.first == "dhcp-ddns") ||
|
||||||
if (config_pair.first == "dhcp-queue-control") {
|
(config_pair.first == "client-classes") ||
|
||||||
DHCPQueueControlParser parser;
|
(config_pair.first == "lease-database") ||
|
||||||
srv_cfg->setDHCPQueueControl(parser.parse(config_pair.second));
|
(config_pair.first == "hosts-database") ||
|
||||||
continue;
|
(config_pair.first == "hosts-databases") ||
|
||||||
}
|
(config_pair.first == "subnet4") ||
|
||||||
|
(config_pair.first == "shared-networks") ||
|
||||||
if (config_pair.first == "host-reservation-identifiers") {
|
(config_pair.first == "reservations") ||
|
||||||
HostReservationIdsParser4 parser;
|
(config_pair.first == "config-control")) {
|
||||||
parser.parse(config_pair.second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "interfaces-config") {
|
|
||||||
ElementPtr ifaces_cfg =
|
|
||||||
boost::const_pointer_cast<Element>(config_pair.second);
|
|
||||||
if (check_only) {
|
|
||||||
// No re-detection in check only mode
|
|
||||||
ifaces_cfg->set("re-detect", Element::create(false));
|
|
||||||
}
|
|
||||||
IfacesConfigParser parser(AF_INET);
|
|
||||||
CfgIfacePtr cfg_iface = srv_cfg->getCfgIface();
|
|
||||||
parser.parse(cfg_iface, ifaces_cfg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "sanity-checks") {
|
|
||||||
SanityChecksParser parser;
|
|
||||||
parser.parse(*srv_cfg, config_pair.second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "expired-leases-processing") {
|
|
||||||
ExpirationConfigParser parser;
|
|
||||||
parser.parse(config_pair.second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The hooks-libraries configuration must be parsed after parsing
|
|
||||||
// multi-threading configuration so that libraries are checked
|
|
||||||
// for multi-threading compatibility.
|
|
||||||
if (config_pair.first == "hooks-libraries") {
|
|
||||||
HooksLibrariesParser hooks_parser;
|
|
||||||
HooksConfig& libraries = srv_cfg->getHooksConfig();
|
|
||||||
hooks_parser.parse(libraries, config_pair.second);
|
|
||||||
libraries.verifyLibraries(config_pair.second->getPosition());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy DhcpConfigParser stuff below
|
|
||||||
if (config_pair.first == "dhcp-ddns") {
|
|
||||||
// Apply defaults
|
|
||||||
D2ClientConfigParser::setAllDefaults(config_pair.second);
|
|
||||||
D2ClientConfigParser parser;
|
|
||||||
d2_client_cfg = parser.parse(config_pair.second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "client-classes") {
|
|
||||||
ClientClassDefListParser parser;
|
|
||||||
ClientClassDictionaryPtr dictionary =
|
|
||||||
parser.parse(config_pair.second, AF_INET);
|
|
||||||
srv_cfg->setClientClassDictionary(dictionary);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Please move at the end when migration will be finished.
|
|
||||||
if (config_pair.first == "lease-database") {
|
|
||||||
db::DbAccessParser parser;
|
|
||||||
std::string access_string;
|
|
||||||
parser.parse(access_string, config_pair.second);
|
|
||||||
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
|
||||||
cfg_db_access->setLeaseDbAccessString(access_string);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "hosts-database") {
|
|
||||||
db::DbAccessParser parser;
|
|
||||||
std::string access_string;
|
|
||||||
parser.parse(access_string, config_pair.second);
|
|
||||||
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
|
||||||
cfg_db_access->setHostDbAccessString(access_string);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "hosts-databases") {
|
|
||||||
CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
|
|
||||||
db::DbAccessParser parser;
|
|
||||||
auto list = config_pair.second->listValue();
|
|
||||||
for (auto it : list) {
|
|
||||||
std::string access_string;
|
|
||||||
parser.parse(access_string, it);
|
|
||||||
cfg_db_access->setHostDbAccessString(access_string);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "subnet4") {
|
|
||||||
Subnets4ListConfigParser subnets_parser;
|
|
||||||
// parse() returns number of subnets parsed. We may log it one day.
|
|
||||||
subnets_parser.parse(srv_cfg, config_pair.second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "shared-networks") {
|
|
||||||
/// We need to create instance of SharedNetworks4ListParser
|
|
||||||
/// and parse the list of the shared networks into the
|
|
||||||
/// CfgSharedNetworks4 object. One additional step is then to
|
|
||||||
/// add subnets from the CfgSharedNetworks4 into CfgSubnets4
|
|
||||||
/// as well.
|
|
||||||
SharedNetworks4ListParser parser;
|
|
||||||
CfgSharedNetworks4Ptr cfg = srv_cfg->getCfgSharedNetworks4();
|
|
||||||
parser.parse(cfg, config_pair.second);
|
|
||||||
|
|
||||||
// We also need to put the subnets it contains into normal
|
|
||||||
// subnets list.
|
|
||||||
global_parser.copySubnets4(srv_cfg->getCfgSubnets4(), cfg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "reservations") {
|
|
||||||
HostCollection hosts;
|
|
||||||
HostReservationsListParser<HostReservationParser4> parser;
|
|
||||||
parser.parse(SUBNET_ID_GLOBAL, config_pair.second, hosts);
|
|
||||||
for (auto h = hosts.begin(); h != hosts.end(); ++h) {
|
|
||||||
srv_cfg->getCfgHosts()->add(*h);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_pair.first == "config-control") {
|
|
||||||
ConfigControlParser parser;
|
|
||||||
ConfigControlInfoPtr config_ctl_info = parser.parse(config_pair.second);
|
|
||||||
CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,6 +642,9 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
<< " (" << config_pair.second->getPosition() << ")");
|
<< " (" << config_pair.second->getPosition() << ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset parameter name.
|
||||||
|
parameter_name = "<post parsing>";
|
||||||
|
|
||||||
// Apply global options in the staging config.
|
// Apply global options in the staging config.
|
||||||
global_parser.parse(srv_cfg, mutable_cfg);
|
global_parser.parse(srv_cfg, mutable_cfg);
|
||||||
|
|
||||||
@@ -620,7 +662,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
|
|
||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
|
||||||
.arg(config_pair.first).arg(ex.what());
|
.arg(parameter_name).arg(ex.what());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
|
||||||
// An error occurred, so make sure that we restore original data.
|
// An error occurred, so make sure that we restore original data.
|
||||||
@@ -628,7 +670,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(config_pair.first);
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
" processing error");
|
" processing error");
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user