diff options
Diffstat (limited to 'src/lib/dhcpsrv/parsers/simple_parser6.cc')
-rw-r--r-- | src/lib/dhcpsrv/parsers/simple_parser6.cc | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/parsers/simple_parser6.cc b/src/lib/dhcpsrv/parsers/simple_parser6.cc new file mode 100644 index 0000000..f7484dd --- /dev/null +++ b/src/lib/dhcpsrv/parsers/simple_parser6.cc @@ -0,0 +1,564 @@ +// Copyright (C) 2016-2023 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <cc/data.h> +#include <dhcpsrv/parsers/simple_parser6.h> + +#include <boost/foreach.hpp> + +using namespace isc::data; + +namespace isc { +namespace dhcp { +/// @brief This sets of arrays define the default values and +/// values inherited (derived) between various scopes. +/// +/// Each of those is documented in @file simple_parser6.cc. This +/// is different than most other comments in Kea code. The reason +/// for placing those in .cc rather than .h file is that it +/// is expected to be one centralized place to look at for +/// the default values. This is expected to be looked at also by +/// people who are not skilled in C or C++, so they may be +/// confused with the differences between declaration and definition. +/// As such, there's one file to look at that hopefully is readable +/// without any C or C++ skills. +/// +/// @{ + +/// @brief This table defines all global parameters in DHCPv6. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows global_param rule in bison grammar. +const SimpleKeywords SimpleParser6::GLOBAL6_PARAMETERS = { + { "data-directory", Element::string }, + { "preferred-lifetime", Element::integer }, + { "min-preferred-lifetime", Element::integer }, + { "max-preferred-lifetime", Element::integer }, + { "valid-lifetime", Element::integer }, + { "min-valid-lifetime", Element::integer }, + { "max-valid-lifetime", Element::integer }, + { "renew-timer", Element::integer }, + { "rebind-timer", Element::integer }, + { "decline-probation-period", Element::integer }, + { "subnet6", Element::list }, + { "shared-networks", Element::list }, + { "interfaces-config", Element::map }, + { "lease-database", Element::map }, + { "hosts-database", Element::map }, + { "hosts-databases", Element::list }, + { "mac-sources", Element::list }, + { "relay-supplied-options", Element::list }, + { "host-reservation-identifiers", Element::list }, + { "client-classes", Element::list }, + { "option-def", Element::list }, + { "option-data", Element::list }, + { "hooks-libraries", Element::list }, + { "expired-leases-processing", Element::map }, + { "server-id", Element::map }, + { "dhcp4o6-port", Element::integer }, + { "control-socket", Element::map }, + { "dhcp-queue-control", Element::map }, + { "dhcp-ddns", Element::map }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "sanity-checks", Element::map }, + { "reservations", Element::list }, + { "config-control", Element::map }, + { "server-tag", Element::string }, + { "reservation-mode", Element::string }, + { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, + { "calculate-tee-times", Element::boolean }, + { "t1-percent", Element::real }, + { "t2-percent", Element::real }, + { "loggers", Element::list }, + { "hostname-char-set", Element::string }, + { "hostname-char-replacement", Element::string }, + { "ddns-send-updates", Element::boolean }, + { "ddns-override-no-update", Element::boolean }, + { "ddns-override-client-update", Element::boolean }, + { "ddns-replace-client-name", Element::string }, + { "ddns-generated-prefix", Element::string }, + { "ddns-qualifying-suffix", Element::string }, + { "store-extended-info", Element::boolean }, + { "statistic-default-sample-count", Element::integer }, + { "statistic-default-sample-age", Element::integer }, + { "multi-threading", Element::map }, + { "cache-threshold", Element::real }, + { "cache-max-age", Element::integer }, + { "early-global-reservations-lookup", Element::boolean }, + { "ip-reservations-unique", Element::boolean }, + { "reservations-lookup-first", Element::boolean }, + { "ddns-update-on-renew", Element::boolean }, + { "ddns-use-conflict-resolution", Element::boolean }, + { "compatibility", Element::map }, + { "parked-packet-limit", Element::integer }, + { "allocator", Element::string }, + { "pd-allocator", Element::string }, + { "ddns-ttl-percent", Element::real }, +}; + +/// @brief This table defines default global values for DHCPv6 +/// +/// Some of the global parameters defined in the global scope (i.e. directly +/// in Dhcp6) are optional. If not defined, the following values will be +/// used. +const SimpleDefaults SimpleParser6::GLOBAL6_DEFAULTS = { + // preferred-lifetime is unspecified and defaults to 0.625 of valid-lifetime. + { "valid-lifetime", Element::integer, "7200" }, + { "decline-probation-period", Element::integer, "86400" }, // 24h + { "dhcp4o6-port", Element::integer, "0" }, + { "server-tag", Element::string, "" }, + { "reservations-global", Element::boolean, "false" }, + { "reservations-in-subnet", Element::boolean, "true" }, + { "reservations-out-of-pool", Element::boolean, "false" }, + { "calculate-tee-times", Element::boolean, "true" }, + { "t1-percent", Element::real, ".50" }, + { "t2-percent", Element::real, ".80" }, + { "ddns-send-updates", Element::boolean, "true" }, + { "ddns-override-no-update", Element::boolean, "false" }, + { "ddns-override-client-update", Element::boolean, "false" }, + { "ddns-replace-client-name", Element::string, "never" }, + { "ddns-generated-prefix", Element::string, "myhost" }, + { "ddns-qualifying-suffix", Element::string, "" }, + { "hostname-char-set", Element::string, "[^A-Za-z0-9.-]" }, + { "hostname-char-replacement", Element::string, "" }, + { "store-extended-info", Element::boolean, "false" }, + { "statistic-default-sample-count", Element::integer, "20" }, + { "statistic-default-sample-age", Element::integer, "0" }, + { "early-global-reservations-lookup", Element::boolean, "false" }, + { "ip-reservations-unique", Element::boolean, "true" }, + { "reservations-lookup-first", Element::boolean, "false" }, + { "ddns-update-on-renew", Element::boolean, "false" }, + { "ddns-use-conflict-resolution", Element::boolean, "true" }, + { "parked-packet-limit", Element::integer, "256" }, + { "allocator", Element::string, "iterative" }, + { "pd-allocator", Element::string, "iterative" }, +}; + +/// @brief This table defines all option definition parameters. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows option_def_param rules in bison grammar. +const SimpleKeywords SimpleParser6::OPTION6_DEF_PARAMETERS = { + { "name", Element::string }, + { "code", Element::integer }, + { "type", Element::string }, + { "record-types", Element::string }, + { "space", Element::string }, + { "encapsulate", Element::string }, + { "array", Element::boolean, }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "metadata", Element::map } +}; + +/// @brief This table defines default values for option definitions in DHCPv6. +/// +/// Dhcp6 may contain an array called option-def that enumerates new option +/// definitions. This array lists default values for those option definitions. +const SimpleDefaults SimpleParser6::OPTION6_DEF_DEFAULTS = { + { "record-types", Element::string, ""}, + { "space", Element::string, "dhcp6"}, // DHCP6_OPTION_SPACE + { "array", Element::boolean, "false"}, + { "encapsulate", Element::string, "" } +}; + +/// @brief This table defines all option parameters. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows option_param rules in bison grammar. +const SimpleKeywords SimpleParser6::OPTION6_PARAMETERS = { + { "name", Element::string }, + { "data", Element::string }, + { "code", Element::integer }, + { "space", Element::string }, + { "csv-format", Element::boolean }, + { "always-send", Element::boolean }, + { "never-send", Element::boolean }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "metadata", Element::map } +}; + +/// @brief This table defines default values for options in DHCPv6. +/// +/// Dhcp6 usually contains option values (option-data) defined in global, +/// subnet, class or host reservations scopes. This array lists default values +/// for those option-data declarations. +const SimpleDefaults SimpleParser6::OPTION6_DEFAULTS = { + { "space", Element::string, "dhcp6"}, // DHCP6_OPTION_SPACE + { "csv-format", Element::boolean, "true"}, + { "always-send", Element::boolean, "false"}, + { "never-send", Element::boolean, "false"} +}; + +/// @brief This table defines all subnet parameters for DHCPv6. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows subnet6_param rule in bison grammar. +const SimpleKeywords SimpleParser6::SUBNET6_PARAMETERS = { + { "preferred-lifetime", Element::integer }, + { "min-preferred-lifetime", Element::integer }, + { "max-preferred-lifetime", Element::integer }, + { "valid-lifetime", Element::integer }, + { "min-valid-lifetime", Element::integer }, + { "max-valid-lifetime", Element::integer }, + { "renew-timer", Element::integer }, + { "rebind-timer", Element::integer }, + { "option-data", Element::list }, + { "pools", Element::list }, + { "pd-pools", Element::list }, + { "subnet", Element::string }, + { "interface", Element::string }, + { "interface-id", Element::string }, + { "id", Element::integer }, + { "rapid-commit", Element::boolean }, + { "client-class", Element::string }, + { "require-client-classes", Element::list }, + { "reservations", Element::list }, + { "reservation-mode", Element::string }, + { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, + { "relay", Element::map }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "calculate-tee-times", Element::boolean }, + { "t1-percent", Element::real }, + { "t2-percent", Element::real }, + { "ddns-send-updates", Element::boolean }, + { "ddns-override-no-update", Element::boolean }, + { "ddns-override-client-update", Element::boolean }, + { "ddns-replace-client-name", Element::string }, + { "ddns-generated-prefix", Element::string }, + { "ddns-qualifying-suffix", Element::string }, + { "hostname-char-set", Element::string }, + { "hostname-char-replacement", Element::string }, + { "store-extended-info", Element::boolean }, + { "metadata", Element::map }, + { "cache-threshold", Element::real }, + { "cache-max-age", Element::integer }, + { "ddns-update-on-renew", Element::boolean }, + { "ddns-use-conflict-resolution", Element::boolean }, + { "allocator", Element::string }, + { "pd-allocator", Element::string }, + { "ddns-ttl-percent", Element::real }, +}; + +/// @brief This table defines default values for each IPv6 subnet. +/// +/// Note: When updating this array, please also update SHARED_SUBNET6_DEFAULTS +/// below. In most cases, those two should be kept in sync, except cases +/// where a parameter can be derived from shared-networks, but is not +/// defined on global level. +const SimpleDefaults SimpleParser6::SUBNET6_DEFAULTS = { + { "id", Element::integer, "0" }, // 0 means autogenerate + { "interface", Element::string, "" }, + { "client-class", Element::string, "" }, + { "rapid-commit", Element::boolean, "false" }, // rapid-commit disabled by default + { "interface-id", Element::string, "" } +}; + +/// @brief This table defines default values for each IPv6 subnet that is +/// part of a shared network +/// +/// This is mostly the same as @ref SUBNET6_DEFAULTS, except the parameters +/// that can be derived from shared-network, but cannot from global scope. +const SimpleDefaults SimpleParser6::SHARED_SUBNET6_DEFAULTS = { + { "id", Element::integer, "0" } // 0 means autogenerate +}; + +/// @brief This table defines default values for each IPv6 shared network. +const SimpleDefaults SimpleParser6::SHARED_NETWORK6_DEFAULTS = { + { "client-class", Element::string, "" }, + { "interface", Element::string, "" }, + { "interface-id", Element::string, "" }, + { "rapid-commit", Element::boolean, "false" } // rapid-commit disabled by default +}; + +/// @brief List of parameters that can be inherited from the global to subnet6 scope. +/// +/// Some parameters may be defined on both global (directly in Dhcp6) and +/// subnet (Dhcp6/subnet6/...) scope. If not defined in the subnet scope, +/// the value is being inherited (derived) from the global scope. This +/// array lists all of such parameters. +/// +/// This list is also used for inheriting from global to shared networks +/// and from shared networks to subnets within it. +const ParamsList SimpleParser6::INHERIT_TO_SUBNET6 = { + "preferred-lifetime", + "min-preferred-lifetime", + "max-preferred-lifetime", + "rebind-timer", + "relay", + "renew-timer", + "valid-lifetime", + "min-valid-lifetime", + "max-valid-lifetime", + "calculate-tee-times", + "t1-percent", + "t2-percent", + "store-extended-info", + "cache-threshold", + "cache-max-age", + "allocator", + "pd-allocator" +}; + +/// @brief This table defines all pool parameters. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows pool_param rules in bison grammar. +const SimpleKeywords SimpleParser6::POOL6_PARAMETERS = { + { "pool", Element::string }, + { "pool-id", Element::integer }, + { "option-data", Element::list }, + { "client-class", Element::string }, + { "require-client-classes", Element::list }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "metadata", Element::map } +}; + +/// @brief This table defines all prefix delegation pool parameters. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows pd_pool_param rules in bison grammar. +const SimpleKeywords SimpleParser6::PD_POOL6_PARAMETERS = { + { "prefix", Element::string }, + { "prefix-len", Element::integer }, + { "delegated-len", Element::integer }, + { "pool-id", Element::integer }, + { "option-data", Element::list }, + { "client-class", Element::string }, + { "require-client-classes", Element::list }, + { "excluded-prefix", Element::string }, + { "excluded-prefix-len", Element::integer }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "metadata", Element::map } +}; + +/// @brief This table defines all shared network parameters for DHCPv6. +/// +/// Boolean, integer, real and string types are for scalar parameters, +/// list and map types for entries. +/// Order follows shared_network_param rule in bison grammar. +const SimpleKeywords SimpleParser6::SHARED_NETWORK6_PARAMETERS = { + { "name", Element::string }, + { "subnet6", Element::list }, + { "interface", Element::string }, + { "interface-id", Element::string }, + { "renew-timer", Element::integer }, + { "rebind-timer", Element::integer }, + { "option-data", Element::list }, + { "relay", Element::map }, + { "reservation-mode", Element::string }, + { "reservations-global", Element::boolean }, + { "reservations-in-subnet", Element::boolean }, + { "reservations-out-of-pool", Element::boolean }, + { "client-class", Element::string }, + { "require-client-classes", Element::list }, + { "preferred-lifetime", Element::integer }, + { "min-preferred-lifetime", Element::integer }, + { "max-preferred-lifetime", Element::integer }, + { "rapid-commit", Element::boolean }, + { "valid-lifetime", Element::integer }, + { "min-valid-lifetime", Element::integer }, + { "max-valid-lifetime", Element::integer }, + { "user-context", Element::map }, + { "comment", Element::string }, + { "calculate-tee-times", Element::boolean }, + { "t1-percent", Element::real }, + { "t2-percent", Element::real }, + { "ddns-send-updates", Element::boolean }, + { "ddns-override-no-update", Element::boolean }, + { "ddns-override-client-update", Element::boolean }, + { "ddns-replace-client-name", Element::string }, + { "ddns-generated-prefix", Element::string }, + { "ddns-qualifying-suffix", Element::string }, + { "hostname-char-set", Element::string }, + { "hostname-char-replacement", Element::string }, + { "store-extended-info", Element::boolean }, + { "metadata", Element::map }, + { "cache-threshold", Element::real }, + { "cache-max-age", Element::integer }, + { "ddns-update-on-renew", Element::boolean }, + { "ddns-use-conflict-resolution", Element::boolean }, + { "allocator", Element::string }, + { "pd-allocator", Element::string }, + { "ddns-ttl-percent", Element::real }, +}; + +/// @brief This table defines default values for interfaces for DHCPv6. +const SimpleDefaults SimpleParser6::IFACE6_DEFAULTS = { + { "re-detect", Element::boolean, "true" } +}; + +/// @brief This table defines default values for dhcp-queue-control in DHCPv6. +const SimpleDefaults SimpleParser6::DHCP_QUEUE_CONTROL6_DEFAULTS = { + { "enable-queue", Element::boolean, "false"}, + { "queue-type", Element::string, "kea-ring6"}, + { "capacity", Element::integer, "64"} +}; + +/// @brief This table defines default values for multi-threading in DHCPv6. +const SimpleDefaults SimpleParser6::DHCP_MULTI_THREADING6_DEFAULTS = { + { "enable-multi-threading", Element::boolean, "true" }, + { "thread-pool-size", Element::integer, "0" }, + { "packet-queue-size", Element::integer, "64" } +}; + +/// @brief This defines default values for sanity checking for DHCPv6. +const SimpleDefaults SimpleParser6::SANITY_CHECKS6_DEFAULTS = { + { "lease-checks", Element::string, "warn" } +}; + +/// @} + +/// --------------------------------------------------------------------------- +/// --- end of default values ------------------------------------------------- +/// --------------------------------------------------------------------------- + +size_t SimpleParser6::setAllDefaults(ElementPtr global) { + size_t cnt = 0; + + // Set global defaults first. + cnt = setDefaults(global, GLOBAL6_DEFAULTS); + + // Now set the defaults for each specified option definition + ConstElementPtr option_defs = global->get("option-def"); + if (option_defs) { + BOOST_FOREACH(ElementPtr option_def, option_defs->listValue()) { + cnt += SimpleParser::setDefaults(option_def, OPTION6_DEF_DEFAULTS); + } + } + + // Set the defaults for option data + ConstElementPtr options = global->get("option-data"); + if (options) { + BOOST_FOREACH(ElementPtr single_option, options->listValue()) { + cnt += SimpleParser::setDefaults(single_option, OPTION6_DEFAULTS); + } + } + + // Now set the defaults for defined subnets + ConstElementPtr subnets = global->get("subnet6"); + if (subnets) { + cnt += setListDefaults(subnets, SUBNET6_DEFAULTS); + } + + // Set the defaults for interfaces config + ConstElementPtr ifaces_cfg = global->get("interfaces-config"); + if (ifaces_cfg) { + ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(ifaces_cfg); + cnt += setDefaults(mutable_cfg, IFACE6_DEFAULTS); + } + + // Set defaults for shared networks + ConstElementPtr shared = global->get("shared-networks"); + if (shared) { + BOOST_FOREACH(ElementPtr net, shared->listValue()) { + + cnt += setDefaults(net, SHARED_NETWORK6_DEFAULTS); + + ConstElementPtr subs = net->get("subnet6"); + if (subs) { + cnt += setListDefaults(subs, SHARED_SUBNET6_DEFAULTS); + } + } + } + + // Set the defaults for dhcp-queue-control. If the element isn't there + // we'll add it. + ConstElementPtr queue_control = global->get("dhcp-queue-control"); + ElementPtr mutable_cfg; + if (queue_control) { + mutable_cfg = boost::const_pointer_cast<Element>(queue_control); + } else { + mutable_cfg = Element::createMap(); + global->set("dhcp-queue-control", mutable_cfg); + } + + cnt += setDefaults(mutable_cfg, DHCP_QUEUE_CONTROL6_DEFAULTS); + + // Set the defaults for multi-threading. If the element isn't there + // we'll add it. + ConstElementPtr multi_threading = global->get("multi-threading"); + if (multi_threading) { + mutable_cfg = boost::const_pointer_cast<Element>(multi_threading); + } else { + mutable_cfg = Element::createMap(); + global->set("multi-threading", mutable_cfg); + } + + cnt += setDefaults(mutable_cfg, DHCP_MULTI_THREADING6_DEFAULTS); + + // Set the defaults for sanity-checks. If the element isn't + // there we'll add it. + ConstElementPtr sanity_checks = global->get("sanity-checks"); + if (sanity_checks) { + mutable_cfg = boost::const_pointer_cast<Element>(sanity_checks); + } else { + mutable_cfg = Element::createMap(); + global->set("sanity-checks", mutable_cfg); + } + + cnt += setDefaults(mutable_cfg, SANITY_CHECKS6_DEFAULTS); + + return (cnt); +} + +size_t SimpleParser6::deriveParameters(ElementPtr global) { + size_t cnt = 0; + + // Now derive global parameters into subnets. + ConstElementPtr subnets = global->get("subnet6"); + if (subnets) { + BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) { + cnt += SimpleParser::deriveParams(global, single_subnet, + INHERIT_TO_SUBNET6); + } + } + + // Deriving parameters for shared networks is a bit more involved. + // First, the shared-network level derives from global, and then + // subnets within derive from it. + ConstElementPtr shared = global->get("shared-networks"); + if (shared) { + BOOST_FOREACH(ElementPtr net, shared->listValue()) { + // First try to inherit the parameters from shared network, + // if defined there. + // Then try to inherit them from global. + cnt += SimpleParser::deriveParams(global, net, + INHERIT_TO_SUBNET6); + + // Now we need to go thrugh all the subnets in this net. + subnets = net->get("subnet6"); + if (subnets) { + BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) { + cnt += SimpleParser::deriveParams(net, single_subnet, + INHERIT_TO_SUBNET6); + } + } + } + } + + return (cnt); +} + +} // namespace dhcp +} // namespace isc |