// 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 = getOptionalParam("renew-timer");
- Triplet<uint32_t> t2 = getOptionalParam("rebind-timer");
+ 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 = getParam("valid-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
Subnet4Ptr subnet4(new Subnet4(addr, len, t1, t2, valid, subnet_id));
subnet_ = subnet4;
- // match-client-id
- isc::util::OptionalValue<bool> match_client_id;
- try {
- match_client_id = boolean_values_->getParam("match-client-id");
-
- } catch (...) {
- // Ignore because this parameter is optional and it may be specified
- // in the global scope.
- }
-
- // If the match-client-id wasn't specified as a subnet specific parameter
- // check if there is global value specified.
- if (!match_client_id.isSpecified()) {
- // If not specified, use false.
- match_client_id.specify(globalContext()->boolean_values_->
- getOptionalParam("match-client-id", true));
- }
-
- // Set the match-client-id value for the subnet.
- subnet4->setMatchClientId(match_client_id.get());
-
- // next-server
- try {
- string next_server = globalContext()->string_values_->getParam("next-server");
- if (!next_server.empty()) {
- subnet4->setSiaddr(IOAddress(next_server));
- }
- } catch (const DhcpConfigError&) {
- // Don't care. next_server is optional. We can live without it
- } catch (...) {
- isc_throw(DhcpConfigError, "invalid parameter next-server ("
- << globalContext()->string_values_->getPosition("next-server")
- << ")");
- }
+ // Set the match-client-id value for the subnet. It is always present.
+ // If not explicitly specified, the default value was filed in when
+ // SimpleParser4::setAllDefaults was called.
+ bool match_client_id = getBoolean(params, "match-client-id");
+ subnet4->setMatchClientId(match_client_id);
- // Try subnet specific value if it's available
+ // 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 {
- string next_server = string_values_->getParam("next-server");
+ next_server = getString(params, "next-server");
if (!next_server.empty()) {
subnet4->setSiaddr(IOAddress(next_server));
}
- } catch (const DhcpConfigError&) {
- // Don't care. next_server is optional. We can live without it
} catch (...) {
- isc_throw(DhcpConfigError, "invalid parameter next-server ("
- << string_values_->getPosition("next-server")
- << ")");
+ ConstElementPtr next = params->find("next-server");
+ string pos("(missing)");
+ if (next)
+ pos = next->getPosition().str();
+ isc_throw(DhcpConfigError, "invalid parameter next-server : "
+ << next_server << "(" << pos << ")");
}
- // Try 4o6 specific parameter: 4o6-interface
- string iface4o6 = string_values_->getOptionalParam("4o6-interface", "");
+ // 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);
}
- // Try 4o6 specific parameter: 4o6-subnet
- string subnet4o6 = string_values_->getOptionalParam("4o6-subnet", "");
+ // 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) {
}
// Try 4o6 specific parameter: 4o6-interface-id
- std::string ifaceid = string_values_->getOptionalParam("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);
}
-
- // Try setting up client class (if specified)
- try {
- string client_class = string_values_->getParam("client-class");
- subnet4->allowClientClass(client_class);
- } catch (const DhcpConfigError&) {
- // That's ok if it fails. client-class is optional.
- }
}
};
{ "dhcp4o6-port", Element::integer, "0" },
{ "echo-client-id", Element::boolean, "true" },
{ "match-client-id", Element::boolean, "true" },
- { "next-server", Element::string, "0.0.0.0" }
+ { "next-server", Element::string, "0.0.0.0" }
};
/// @brief This table defines default values for each IPv4 subnet.
const SimpleDefaults SimpleParser4::SUBNET4_DEFAULTS = {
- { "id", Element::integer, "0" } // 0 means autogenerate
+ { "id", Element::integer, "0" }, // 0 means autogenerate
+ { "interface", Element::string, "" },
+ { "client-class", Element::string, "" },
+ { "reservation-mode", Element::string, "all" },
+ { "4o6-interface", Element::string, "" },
+ { "4o6-interface-id", Element::string, "" },
+ { "4o6-subnet", Element::string, "" },
};
/// @brief List of parameters that can be inherited from the global to subnet4 scope.
// 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 = getParam("renew-timer");
- Triplet<uint32_t> t2 = getParam("rebind-timer");
- Triplet<uint32_t> pref = getParam("preferred-lifetime");
- Triplet<uint32_t> valid = getParam("valid-lifetime");
+ 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"));
- // Get interface-id option content. For now we support string
- // representation only
- std::string ifaceid;
- try {
- ifaceid = string_values_->getParam("interface-id");
- } catch (const DhcpConfigError &) {
- // interface-id is not mandatory
- }
-
- // Specifying both interface for locally reachable subnets and
- // interface id for relays is mutually exclusive. Need to test for
- // this condition.
- if (!ifaceid.empty()) {
- std::string iface;
- try {
- iface = string_values_->getParam("interface");
- } catch (const DhcpConfigError &) {
- // iface not mandatory
- }
-
- if (!iface.empty()) {
- isc_throw(isc::dhcp::DhcpConfigError,
- "parser error: interface (defined for locally reachable "
- "subnets) and interface-id (defined for subnets reachable"
- " via relays) cannot be defined at the same time for "
- "subnet " << addr << "/" << (int)len);
- }
- }
-
- // Gather boolean parameters values.
bool rapid_commit = getBoolean(params, "rapid-commit");
std::ostringstream output;
Subnet6* subnet6 = new Subnet6(addr, len, t1, t2, pref, valid,
subnet_id);
+ // 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,
+ "parser error: interface (defined for locally reachable "
+ "subnets) and interface-id (defined for subnets reachable"
+ " via relays) cannot be defined at the same time for "
+ "subnet " << addr << "/" << (int)len);
+ }
+
// Configure interface-id for remote interfaces, if defined
if (!ifaceid.empty()) {
OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
// Enable or disable Rapid Commit option support for the subnet.
subnet6->setRapidCommit(rapid_commit);
- // Try setting up client class (if specified)
- try {
- string client_class = string_values_->getParam("client-class");
- subnet6->allowClientClass(client_class);
- } catch (const DhcpConfigError&) {
- // That's ok if it fails. client-class is optional.
- }
-
subnet_.reset(subnet6);
}
/// @brief This table defines default values for each IPv6 subnet.
const SimpleDefaults SimpleParser6::SUBNET6_DEFAULTS = {
- { "id", Element::integer, "0" }, // 0 means autogenerate
- { "rapid-commit", Element::boolean, "false" } // rapid-commit disabled by default
+ { "id", Element::integer, "0" }, // 0 means autogenerate
+ { "interface", Element::string, "" },
+ { "client-class", Element::string, "" },
+ { "reservation-mode", Element::string, "all" },
+ { "rapid-commit", Element::boolean, "false" }, // rapid-commit disabled by default
+ { "interface-id", Element::string, "" },
};
/// @brief List of parameters that can be inherited from the global to subnet6 scope.
subnet_->addPool(*it);
}
- // Configure interface, if defined
+ // Now configure parameters that are common for v4 and v6:
// Get interface name. If it is defined, then the subnet is available
// directly over specified network interface.
- std::string iface;
- try {
- iface = string_values_->getParam("interface");
- } catch (const DhcpConfigError &) {
- // iface not mandatory so swallow the exception
+ std::string iface = getString(params, "interface");
+ if (!iface.empty()) {
+ if (!IfaceMgr::instance().getIface(iface)) {
+ isc_throw(DhcpConfigError, "Specified network interface name " << iface
+ << " for subnet " << subnet_->toText()
+ << " is not present" << " in the system ("
+ << string_values_->getPosition("interface") << ")");
+ }
+
+ subnet_->setIface(iface);
}
// Let's set host reservation mode. If not specified, the default value of
// all will be used.
- std::string hr_mode;
try {
- hr_mode = string_values_->getOptionalParam("reservation-mode", "all");
+ std::string hr_mode = getString(params, "reservation-mode");
subnet_->setHostReservationMode(hrModeFromText(hr_mode));
} catch (const BadValue& ex) {
+ ConstElementPtr mode = params->find("reservation-mode");
+ string pos("[missing]");
+ if (mode) {
+ pos = mode->getPosition().str();
+ }
isc_throw(DhcpConfigError, "Failed to process specified value "
" of reservation-mode parameter: " << ex.what()
- << string_values_->getPosition("reservation-mode"));
+ << "(" << pos << ")");
}
- if (!iface.empty()) {
- if (!IfaceMgr::instance().getIface(iface)) {
- isc_throw(DhcpConfigError, "Specified interface name " << iface
- << " for subnet " << subnet_->toText()
- << " is not present" << " in the system ("
- << string_values_->getPosition("interface") << ")");
- }
-
- subnet_->setIface(iface);
+ // Try setting up client class.
+ string client_class = getString(params, "client-class");
+ if (!client_class.empty()) {
+ subnet_->allowClientClass(client_class);
}
// Here globally defined options were merged to the subnet specific
D2ClientConfigPtr
D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) {
D2ClientConfigPtr new_config;
-
+
if (isShortCutDisabled(client_config)) {
// If enable-updates is the only parameter and it is false then
// we're done. This allows for an abbreviated configuration entry
/// @brief this class parses a single subnet
///
-/// This class parses the whole subnet definition. It creates parsers
-/// for received configuration parameters as needed.
+/// There are dedicated @ref Subnet4ConfigParser and @ref Subnet6ConfigParser
+/// classes. They provide specialized parse() methods that return Subnet4Ptr
+/// or Subnet6Ptr.
+///
+/// This class parses the whole subnet definition. This class attempts to
+/// unify the code between v4 and v6 as much as possible. As a result, the flow
+/// is somewhat complex and it looks as follows:
+///
+/// ------- Base class
+/// /
+/// | /----- Derived class
+/// 1. * SubnetXConfigParser::parse() is called.
+/// 2. * SubnetConfigParser::parse() is called.
+/// 3. * SubnetConfigParser::createSubnet() is called.
+/// 4. * SubnetXConfigParser::initSubnet() is called (Subnet4 or Subnet6 is
+/// instantiated here and family specific parameters are set)
+/// 5. Control returns to createSubnet() (step 3) and common parameters
+/// are set.
+
class SubnetConfigParser : public isc::data::SimpleParser {
public: