// Rollback informs whether error occurred and original data
// have to be restored to global storages.
bool rollback = false;
- // config_pair holds the details of the current parser when iterating over
- // the parsers. It is declared outside the loops so in case of an error,
- // the name of the failing parser can be retrieved in the "catch" clause.
- ConfigPair config_pair;
+ // Global parameter name in case of an error.
+ string parameter_name;
ElementPtr mutable_cfg;
SrvConfigPtr srv_cfg;
try {
// And now derive (inherit) global parameters to subnets, if not specified.
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
ConstElementPtr option_defs = mutable_cfg->get("option-def");
if (option_defs) {
+ parameter_name = "option-def";
OptionDefListParser parser(AF_INET);
CfgOptionDefPtr cfg_option_def = srv_cfg->getCfgOptionDef();
parser.parse(cfg_option_def, option_defs);
}
- // This parser is used in several places, so it should be available
- // early.
- Dhcp4ConfigParser global_parser;
-
- // D2 client configuration.
- D2ClientConfigPtr d2_client_cfg;
+ ConstElementPtr option_datas = mutable_cfg->get("option-data");
+ if (option_datas) {
+ parameter_name = "option-data";
+ OptionDataListParser parser(AF_INET);
+ CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
+ parser.parse(cfg_option, option_datas);
+ }
- // Make parsers grouping.
- const std::map<std::string, ConstElementPtr>& values_map =
- mutable_cfg->mapValue();
- 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;
- }
+ ConstElementPtr control_socket = mutable_cfg->get("control-socket");
+ if (control_socket) {
+ parameter_name = "control-socket";
+ ControlSocketParser parser;
+ parser.parse(*srv_cfg, control_socket);
+ }
- if (config_pair.first == "option-data") {
- OptionDataListParser parser(AF_INET);
- CfgOptionPtr cfg_option = srv_cfg->getCfgOption();
- parser.parse(cfg_option, config_pair.second);
- continue;
- }
+ ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
+ if (multi_threading) {
+ parameter_name = "multi-threading";
+ MultiThreadingConfigParser parser;
+ parser.parse(*srv_cfg, multi_threading);
+ }
- if (config_pair.first == "control-socket") {
- ControlSocketParser parser;
- parser.parse(*srv_cfg, config_pair.second);
- continue;
- }
+ 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));
+ }
- if (config_pair.first == "multi-threading") {
- MultiThreadingConfigParser parser;
- parser.parse(*srv_cfg, config_pair.second);
- continue;
- }
+ ConstElementPtr hr_identifiers =
+ mutable_cfg->get("host-reservation-identifiers");
+ if (hr_identifiers) {
+ parameter_name = "host-reservation-identifiers";
+ HostReservationIdsParser4 parser;
+ parser.parse(hr_identifiers);
+ }
- if (config_pair.first == "dhcp-queue-control") {
- DHCPQueueControlParser parser;
- srv_cfg->setDHCPQueueControl(parser.parse(config_pair.second));
- continue;
+ 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);
+ }
- if (config_pair.first == "host-reservation-identifiers") {
- HostReservationIdsParser4 parser;
- parser.parse(config_pair.second);
- continue;
- }
+ ConstElementPtr sanity_checks = mutable_cfg->get("sanity-checks");
+ if (sanity_checks) {
+ parameter_name = "sanity-checks";
+ SanityChecksParser parser;
+ parser.parse(*srv_cfg, sanity_checks);
+ }
- 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;
- }
+ ConstElementPtr expiration_cfg =
+ mutable_cfg->get("expired-leases-processing");
+ if (expiration_cfg) {
+ parameter_name = "expired-leases-processing";
+ ExpirationConfigParser parser;
+ parser.parse(expiration_cfg);
+ }
- if (config_pair.first == "sanity-checks") {
- SanityChecksParser parser;
- parser.parse(*srv_cfg, 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.
+ 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());
+ }
- if (config_pair.first == "expired-leases-processing") {
- ExpirationConfigParser parser;
- parser.parse(config_pair.second);
- continue;
- }
+ // D2 client configuration.
+ D2ClientConfigPtr d2_client_cfg;
- // 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.
+ 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);
+ }
- // 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;
- }
+ 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);
+ }
- 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.
+ 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);
+ }
- // 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;
- }
+ 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);
+ }
- if (config_pair.first == "hosts-database") {
- db::DbAccessParser parser;
+ 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, config_pair.second);
- CfgDbAccessPtr cfg_db_access = srv_cfg->getCfgDbAccess();
+ parser.parse(access_string, it);
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;
- }
+ 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);
+ }
- 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;
- }
+ // This parser is used in several places.
+ Dhcp4ConfigParser global_parser;
- 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;
+ 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);
}
+ }
- 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);
- }
+ 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);
+ }
- continue;
- }
+ // Make parsers grouping.
+ ConfigPair config_pair;
+ const std::map<std::string, ConstElementPtr>& values_map =
+ mutable_cfg->mapValue();
+ BOOST_FOREACH(config_pair, values_map) {
- if (config_pair.first == "config-control") {
- ConfigControlParser parser;
- ConfigControlInfoPtr config_ctl_info = parser.parse(config_pair.second);
- CfgMgr::instance().getStagingCfg()->setConfigControlInfo(config_ctl_info);
+ parameter_name = config_pair.first;
+
+ // These are converted to SimpleParser and are handled already above.
+ if ((config_pair.first == "option-def") ||
+ (config_pair.first == "option-data") ||
+ (config_pair.first == "control-socket") ||
+ (config_pair.first == "multi-threading") ||
+ (config_pair.first == "dhcp-queue-control") ||
+ (config_pair.first == "host-reservation-identifiers") ||
+ (config_pair.first == "interfaces-config") ||
+ (config_pair.first == "sanity-checks") ||
+ (config_pair.first == "expired-leases-processing") ||
+ (config_pair.first == "hooks-libraries") ||
+ (config_pair.first == "dhcp-ddns") ||
+ (config_pair.first == "client-classes") ||
+ (config_pair.first == "lease-database") ||
+ (config_pair.first == "hosts-database") ||
+ (config_pair.first == "hosts-databases") ||
+ (config_pair.first == "subnet4") ||
+ (config_pair.first == "shared-networks") ||
+ (config_pair.first == "reservations") ||
+ (config_pair.first == "config-control")) {
continue;
}
<< " (" << config_pair.second->getPosition() << ")");
}
+ // Reset parameter name.
+ parameter_name = "<post parsing>";
+
// Apply global options in the staging config.
global_parser.parse(srv_cfg, mutable_cfg);
} catch (const isc::Exception& ex) {
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());
// An error occurred, so make sure that we restore original data.
} catch (...) {
// 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"
" processing error");