| File: | home/fedora/workspace/kea-dev/clang-static-analyzer/build/meson-private/tmpxsedttj5/../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc |
| Warning: | line 936, column 13 Value stored to 'len' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // Copyright (C) 2013-2025 Internet Systems Consortium, Inc. ("ISC") |
| 2 | // |
| 3 | // This Source Code Form is subject to the terms of the Mozilla Public |
| 4 | // License, v. 2.0. If a copy of the MPL was not distributed with this |
| 5 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6 | |
| 7 | #include <config.h> |
| 8 | |
| 9 | #include <config/http_command_config.h> |
| 10 | #include <config/unix_command_config.h> |
| 11 | #include <dhcp/iface_mgr.h> |
| 12 | #include <dhcp/dhcp4.h> |
| 13 | #include <dhcp/libdhcp++.h> |
| 14 | #include <dhcpsrv/cfgmgr.h> |
| 15 | #include <dhcpsrv/cfg_option.h> |
| 16 | #include <dhcpsrv/dhcpsrv_log.h> |
| 17 | #include <dhcpsrv/parsers/dhcp_parsers.h> |
| 18 | #include <dhcpsrv/parsers/host_reservation_parser.h> |
| 19 | #include <dhcpsrv/parsers/host_reservations_list_parser.h> |
| 20 | #include <dhcpsrv/parsers/option_data_parser.h> |
| 21 | #include <dhcpsrv/parsers/simple_parser4.h> |
| 22 | #include <dhcpsrv/parsers/simple_parser6.h> |
| 23 | #include <dhcpsrv/cfg_mac_source.h> |
| 24 | #include <util/encode/encode.h> |
| 25 | #include <util/str.h> |
| 26 | |
| 27 | #include <boost/algorithm/string.hpp> |
| 28 | #include <boost/foreach.hpp> |
| 29 | #include <boost/lexical_cast.hpp> |
| 30 | #include <boost/make_shared.hpp> |
| 31 | #include <boost/scoped_ptr.hpp> |
| 32 | |
| 33 | #include <limits> |
| 34 | #include <map> |
| 35 | #include <string> |
| 36 | #include <vector> |
| 37 | #include <iomanip> |
| 38 | |
| 39 | using namespace std; |
| 40 | using namespace isc::asiolink; |
| 41 | using namespace isc::config; |
| 42 | using namespace isc::data; |
| 43 | using namespace isc::util; |
| 44 | namespace ph = std::placeholders; |
| 45 | |
| 46 | namespace isc { |
| 47 | namespace dhcp { |
| 48 | |
| 49 | // ******************** MACSourcesListConfigParser ************************* |
| 50 | |
| 51 | void |
| 52 | MACSourcesListConfigParser::parse(CfgMACSource& mac_sources, ConstElementPtr value) { |
| 53 | uint32_t source = 0; |
| 54 | size_t cnt = 0; |
| 55 | |
| 56 | // By default, there's only one source defined: ANY. |
| 57 | // If user specified anything, we need to get rid of that default. |
| 58 | mac_sources.clear(); |
| 59 | |
| 60 | for (auto const& source_elem : value->listValue()) { |
| 61 | std::string source_str = source_elem->stringValue(); |
| 62 | try { |
| 63 | source = CfgMACSource::MACSourceFromText(source_str); |
| 64 | mac_sources.add(source); |
| 65 | ++cnt; |
| 66 | } catch (const InvalidParameter& ex) { |
| 67 | isc_throw(DhcpConfigError, "The mac-sources value '" << source_strdo { std::ostringstream oss__; oss__ << "The mac-sources value '" << source_str << "' was specified twice (" << value->getPosition() << ")"; throw DhcpConfigError( "../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 68, oss__ .str().c_str()); } while (1) |
| 68 | << "' was specified twice (" << value->getPosition() << ")")do { std::ostringstream oss__; oss__ << "The mac-sources value '" << source_str << "' was specified twice (" << value->getPosition() << ")"; throw DhcpConfigError( "../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 68, oss__ .str().c_str()); } while (1); |
| 69 | } catch (const std::exception& ex) { |
| 70 | isc_throw(DhcpConfigError, "Failed to convert '"do { std::ostringstream oss__; oss__ << "Failed to convert '" << source_str << "' to any recognized MAC source:" << ex.what() << " (" << value->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 72, oss__.str().c_str()); } while (1) |
| 71 | << source_str << "' to any recognized MAC source:"do { std::ostringstream oss__; oss__ << "Failed to convert '" << source_str << "' to any recognized MAC source:" << ex.what() << " (" << value->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 72, oss__.str().c_str()); } while (1) |
| 72 | << ex.what() << " (" << value->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to convert '" << source_str << "' to any recognized MAC source:" << ex.what() << " (" << value->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 72, oss__.str().c_str()); } while (1); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | if (!cnt) { |
| 77 | isc_throw(DhcpConfigError, "If specified, MAC Sources cannot be empty")do { std::ostringstream oss__; oss__ << "If specified, MAC Sources cannot be empty" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 77, oss__.str().c_str()); } while (1); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | // ******************** ControlSocketsParser ************************* |
| 82 | void ControlSocketsParser::parse(SrvConfig& srv_cfg, ConstElementPtr value) { |
| 83 | if (value->getType() != Element::list) { |
| 84 | // Sanity check: not supposed to fail. |
| 85 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 86, oss__.str().c_str()); } while (1) |
| 86 | "Specified control-sockets is expected to be a list")do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 86, oss__.str().c_str()); } while (1); |
| 87 | } |
| 88 | bool seen_unix(false); |
| 89 | ElementPtr unix_config = Element::createList(); |
| 90 | ElementPtr http_config = Element::createList(); |
| 91 | for (ElementPtr socket : value->listValue()) { |
| 92 | if (socket->getType() != Element::map) { |
| 93 | // Sanity check: not supposed to fail. |
| 94 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list of maps" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 95, oss__.str().c_str()); } while (1) |
| 95 | "Specified control-sockets is expected to be a list of maps")do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list of maps" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 95, oss__.str().c_str()); } while (1); |
| 96 | } |
| 97 | ConstElementPtr socket_type = socket->get("socket-type"); |
| 98 | if (!socket_type) { |
| 99 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "'socket-type' parameter is mandatory in control-sockets items" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 100, oss__.str().c_str()); } while (1) |
| 100 | "'socket-type' parameter is mandatory in control-sockets items")do { std::ostringstream oss__; oss__ << "'socket-type' parameter is mandatory in control-sockets items" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 100, oss__.str().c_str()); } while (1); |
| 101 | } |
| 102 | if (socket_type->getType() != Element::string) { |
| 103 | // Sanity check: not supposed to fail. |
| 104 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "'socket-type' parameter is expected to be a string" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 105, oss__.str().c_str()); } while (1) |
| 105 | "'socket-type' parameter is expected to be a string")do { std::ostringstream oss__; oss__ << "'socket-type' parameter is expected to be a string" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 105, oss__.str().c_str()); } while (1); |
| 106 | } |
| 107 | string type = socket_type->stringValue(); |
| 108 | if (type == "unix") { |
| 109 | if (seen_unix) { |
| 110 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "control socket of type 'unix' already configured" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 111, oss__.str().c_str()); } while (1) |
| 111 | "control socket of type 'unix' already configured")do { std::ostringstream oss__; oss__ << "control socket of type 'unix' already configured" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 111, oss__.str().c_str()); } while (1); |
| 112 | } |
| 113 | UnixCommandConfig cmd_config(socket); |
| 114 | seen_unix = true; |
| 115 | unix_config->add(socket); |
| 116 | } else if ((type == "http") || (type == "https")) { |
| 117 | HttpCommandConfig cmd_config(socket); |
| 118 | http_config->add(socket); |
| 119 | } else { |
| 120 | // Sanity check: not supposed to fail. |
| 121 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "unsupported 'socket-type': '" << type << "' not 'unix', 'http' or 'https'"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 123, oss__.str().c_str()); } while (1) |
| 122 | "unsupported 'socket-type': '" << typedo { std::ostringstream oss__; oss__ << "unsupported 'socket-type': '" << type << "' not 'unix', 'http' or 'https'"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 123, oss__.str().c_str()); } while (1) |
| 123 | << "' not 'unix', 'http' or 'https'")do { std::ostringstream oss__; oss__ << "unsupported 'socket-type': '" << type << "' not 'unix', 'http' or 'https'"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 123, oss__.str().c_str()); } while (1); |
| 124 | } |
| 125 | } |
| 126 | if (unix_config->size()) { |
| 127 | srv_cfg.setUnixControlSocketInfo(unix_config); |
| 128 | } |
| 129 | if (http_config->size()) { |
| 130 | srv_cfg.setHttpControlSocketInfo(http_config); |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | // ******************************** OptionDefParser **************************** |
| 135 | |
| 136 | OptionDefParser::OptionDefParser(const uint16_t address_family) |
| 137 | : address_family_(address_family) { |
| 138 | } |
| 139 | |
| 140 | OptionDefinitionPtr |
| 141 | OptionDefParser::parse(ConstElementPtr option_def) { |
| 142 | |
| 143 | // Check parameters. |
| 144 | if (address_family_ == AF_INET2) { |
| 145 | checkKeywords(SimpleParser4::OPTION4_DEF_PARAMETERS, option_def); |
| 146 | } else { |
| 147 | checkKeywords(SimpleParser6::OPTION6_DEF_PARAMETERS, option_def); |
| 148 | } |
| 149 | |
| 150 | // Get mandatory parameters. |
| 151 | std::string name = getString(option_def, "name"); |
| 152 | int64_t code64 = getInteger(option_def, "code"); |
| 153 | std::string type = getString(option_def, "type"); |
| 154 | |
| 155 | // Get optional parameters. Whoever called this parser, should have |
| 156 | // called SimpleParser::setDefaults first. |
| 157 | bool array_type = getBoolean(option_def, "array"); |
| 158 | std::string record_types = getString(option_def, "record-types"); |
| 159 | std::string space = getString(option_def, "space"); |
| 160 | std::string encapsulates = getString(option_def, "encapsulate"); |
| 161 | ConstElementPtr user_context = option_def->get("user-context"); |
| 162 | |
| 163 | // Check code value. |
| 164 | if (code64 < 0) { |
| 165 | isc_throw(DhcpConfigError, "option code must not be negative "do { std::ostringstream oss__; oss__ << "option code must not be negative " "(" << getPosition("code", option_def) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 166, oss__.str().c_str()); } while (1) |
| 166 | "(" << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "option code must not be negative " "(" << getPosition("code", option_def) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 166, oss__.str().c_str()); } while (1); |
| 167 | } else if (address_family_ == AF_INET2 && |
| 168 | code64 > std::numeric_limits<uint8_t>::max()) { |
| 169 | isc_throw(DhcpConfigError, "invalid option code '" << code64do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << static_cast<int>(std::numeric_limits<uint8_t>::max ()) << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 172, oss__.str().c_str()); } while (1) |
| 170 | << "', it must not be greater than '"do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << static_cast<int>(std::numeric_limits<uint8_t>::max ()) << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 172, oss__.str().c_str()); } while (1) |
| 171 | << static_cast<int>(std::numeric_limits<uint8_t>::max())do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << static_cast<int>(std::numeric_limits<uint8_t>::max ()) << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 172, oss__.str().c_str()); } while (1) |
| 172 | << "' (" << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << static_cast<int>(std::numeric_limits<uint8_t>::max ()) << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 172, oss__.str().c_str()); } while (1); |
| 173 | } else if (address_family_ == AF_INET610 && |
| 174 | code64 > std::numeric_limits<uint16_t>::max()) { |
| 175 | isc_throw(DhcpConfigError, "invalid option code '" << code64do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << std::numeric_limits<uint16_t>::max() << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 178, oss__ .str().c_str()); } while (1) |
| 176 | << "', it must not be greater than '"do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << std::numeric_limits<uint16_t>::max() << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 178, oss__ .str().c_str()); } while (1) |
| 177 | << std::numeric_limits<uint16_t>::max()do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << std::numeric_limits<uint16_t>::max() << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 178, oss__ .str().c_str()); } while (1) |
| 178 | << "' (" << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '" << code64 << "', it must not be greater than '" << std::numeric_limits<uint16_t>::max() << "' (" << getPosition("code", option_def) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 178, oss__ .str().c_str()); } while (1); |
| 179 | } |
| 180 | uint32_t code = static_cast<uint32_t>(code64); |
| 181 | |
| 182 | // Validate space name. |
| 183 | if (!OptionSpace::validateName(space)) { |
| 184 | isc_throw(DhcpConfigError, "invalid option space name '"do { std::ostringstream oss__; oss__ << "invalid option space name '" << space << "' (" << getPosition("space", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 186, oss__.str().c_str()); } while (1) |
| 185 | << space << "' ("do { std::ostringstream oss__; oss__ << "invalid option space name '" << space << "' (" << getPosition("space", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 186, oss__.str().c_str()); } while (1) |
| 186 | << getPosition("space", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option space name '" << space << "' (" << getPosition("space", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 186, oss__.str().c_str()); } while (1); |
| 187 | } |
| 188 | |
| 189 | // Protect against definition of options 0 (PAD) or 255 (END) |
| 190 | // in (and only in) the dhcp4 space. |
| 191 | if (space == DHCP4_OPTION_SPACE"dhcp4") { |
| 192 | if (code == DHO_PAD) { |
| 193 | isc_throw(DhcpConfigError, "invalid option code '0': "do { std::ostringstream oss__; oss__ << "invalid option code '0': " << "reserved for PAD (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 195, oss__.str().c_str()); } while (1) |
| 194 | << "reserved for PAD ("do { std::ostringstream oss__; oss__ << "invalid option code '0': " << "reserved for PAD (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 195, oss__.str().c_str()); } while (1) |
| 195 | << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '0': " << "reserved for PAD (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 195, oss__.str().c_str()); } while (1); |
| 196 | } else if (code == DHO_END) { |
| 197 | isc_throw(DhcpConfigError, "invalid option code '255': "do { std::ostringstream oss__; oss__ << "invalid option code '255': " << "reserved for END (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 199, oss__.str().c_str()); } while (1) |
| 198 | << "reserved for END ("do { std::ostringstream oss__; oss__ << "invalid option code '255': " << "reserved for END (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 199, oss__.str().c_str()); } while (1) |
| 199 | << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '255': " << "reserved for END (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 199, oss__.str().c_str()); } while (1); |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | // For dhcp6 space the value 0 is reserved. |
| 204 | if (space == DHCP6_OPTION_SPACE"dhcp6") { |
| 205 | if (code == 0) { |
| 206 | isc_throw(DhcpConfigError, "invalid option code '0': "do { std::ostringstream oss__; oss__ << "invalid option code '0': " << "reserved value (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 208, oss__.str().c_str()); } while (1) |
| 207 | << "reserved value ("do { std::ostringstream oss__; oss__ << "invalid option code '0': " << "reserved value (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 208, oss__.str().c_str()); } while (1) |
| 208 | << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '0': " << "reserved value (" << getPosition("code", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 208, oss__.str().c_str()); } while (1); |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | // Create option definition. |
| 213 | OptionDefinitionPtr def; |
| 214 | // We need to check if user has set encapsulated option space |
| 215 | // name. If so, different constructor will be used. |
| 216 | if (!encapsulates.empty()) { |
| 217 | // Arrays can't be used together with sub-options. |
| 218 | if (array_type) { |
| 219 | isc_throw(DhcpConfigError, "option '" << space << "."do { std::ostringstream oss__; oss__ << "option '" << space << "." << name << "', comprising an array of data" << " fields may not encapsulate any option space (" << option_def->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 222, oss__ .str().c_str()); } while (1) |
| 220 | << name << "', comprising an array of data"do { std::ostringstream oss__; oss__ << "option '" << space << "." << name << "', comprising an array of data" << " fields may not encapsulate any option space (" << option_def->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 222, oss__ .str().c_str()); } while (1) |
| 221 | << " fields may not encapsulate any option space ("do { std::ostringstream oss__; oss__ << "option '" << space << "." << name << "', comprising an array of data" << " fields may not encapsulate any option space (" << option_def->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 222, oss__ .str().c_str()); } while (1) |
| 222 | << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << "option '" << space << "." << name << "', comprising an array of data" << " fields may not encapsulate any option space (" << option_def->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 222, oss__ .str().c_str()); } while (1); |
| 223 | |
| 224 | } else if (encapsulates == space) { |
| 225 | isc_throw(DhcpConfigError, "option must not encapsulate"do { std::ostringstream oss__; oss__ << "option must not encapsulate" << " an option space it belongs to: '" << space << "." << name << "' is set to" << " encapsulate '" << space << "' (" << option_def->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 229, oss__.str().c_str()); } while (1) |
| 226 | << " an option space it belongs to: '"do { std::ostringstream oss__; oss__ << "option must not encapsulate" << " an option space it belongs to: '" << space << "." << name << "' is set to" << " encapsulate '" << space << "' (" << option_def->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 229, oss__.str().c_str()); } while (1) |
| 227 | << space << "." << name << "' is set to"do { std::ostringstream oss__; oss__ << "option must not encapsulate" << " an option space it belongs to: '" << space << "." << name << "' is set to" << " encapsulate '" << space << "' (" << option_def->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 229, oss__.str().c_str()); } while (1) |
| 228 | << " encapsulate '" << space << "' ("do { std::ostringstream oss__; oss__ << "option must not encapsulate" << " an option space it belongs to: '" << space << "." << name << "' is set to" << " encapsulate '" << space << "' (" << option_def->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 229, oss__.str().c_str()); } while (1) |
| 229 | << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << "option must not encapsulate" << " an option space it belongs to: '" << space << "." << name << "' is set to" << " encapsulate '" << space << "' (" << option_def->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 229, oss__.str().c_str()); } while (1); |
| 230 | |
| 231 | } else { |
| 232 | def.reset(new OptionDefinition(name, code, space, type, |
| 233 | encapsulates.c_str())); |
| 234 | } |
| 235 | |
| 236 | } else { |
| 237 | def.reset(new OptionDefinition(name, code, space, type, array_type)); |
| 238 | |
| 239 | } |
| 240 | |
| 241 | if (user_context) { |
| 242 | def->setContext(user_context); |
| 243 | } |
| 244 | |
| 245 | // Split the list of record types into tokens. |
| 246 | std::vector<std::string> record_tokens = |
| 247 | isc::util::str::tokens(record_types, ","); |
| 248 | // Iterate over each token and add a record type into |
| 249 | // option definition. |
| 250 | for (auto const& record_type : record_tokens) { |
| 251 | try { |
| 252 | auto const trim_rec = boost::trim_copy(record_type); |
| 253 | if (!trim_rec.empty()) { |
| 254 | def->addRecordField(trim_rec); |
| 255 | } |
| 256 | } catch (const Exception& ex) { |
| 257 | isc_throw(DhcpConfigError, "invalid record type values"do { std::ostringstream oss__; oss__ << "invalid record type values" << " specified for the option definition: " << ex .what() << " (" << getPosition("record-types", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 260, oss__.str().c_str()); } while (1) |
| 258 | << " specified for the option definition: "do { std::ostringstream oss__; oss__ << "invalid record type values" << " specified for the option definition: " << ex .what() << " (" << getPosition("record-types", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 260, oss__.str().c_str()); } while (1) |
| 259 | << ex.what() << " ("do { std::ostringstream oss__; oss__ << "invalid record type values" << " specified for the option definition: " << ex .what() << " (" << getPosition("record-types", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 260, oss__.str().c_str()); } while (1) |
| 260 | << getPosition("record-types", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid record type values" << " specified for the option definition: " << ex .what() << " (" << getPosition("record-types", option_def ) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 260, oss__.str().c_str()); } while (1); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | // Validate the definition. |
| 265 | try { |
| 266 | def->validate(); |
| 267 | } catch (const std::exception& ex) { |
| 268 | isc_throw(DhcpConfigError, ex.what()do { std::ostringstream oss__; oss__ << ex.what() << " (" << option_def->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 269, oss__.str().c_str()); } while (1) |
| 269 | << " (" << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << option_def->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 269, oss__.str().c_str()); } while (1); |
| 270 | } |
| 271 | |
| 272 | // Option definition has been created successfully. |
| 273 | return (def); |
| 274 | } |
| 275 | |
| 276 | // ******************************** OptionDefListParser ************************ |
| 277 | |
| 278 | OptionDefListParser::OptionDefListParser(const uint16_t address_family) |
| 279 | : address_family_(address_family) { |
| 280 | } |
| 281 | |
| 282 | void |
| 283 | OptionDefListParser::parse(CfgOptionDefPtr storage, ConstElementPtr option_def_list) { |
| 284 | if (!option_def_list) { |
| 285 | // Sanity check: not supposed to fail. |
| 286 | isc_throw(DhcpConfigError, "parser error: a pointer to a list of"do { std::ostringstream oss__; oss__ << "parser error: a pointer to a list of" << " option definitions is NULL (" << option_def_list ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 288, oss__.str().c_str()); } while (1) |
| 287 | << " option definitions is NULL ("do { std::ostringstream oss__; oss__ << "parser error: a pointer to a list of" << " option definitions is NULL (" << option_def_list ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 288, oss__.str().c_str()); } while (1) |
| 288 | << option_def_list->getPosition() << ")")do { std::ostringstream oss__; oss__ << "parser error: a pointer to a list of" << " option definitions is NULL (" << option_def_list ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 288, oss__.str().c_str()); } while (1); |
| 289 | } |
| 290 | |
| 291 | OptionDefParser parser(address_family_); |
| 292 | for (auto const& option_def : option_def_list->listValue()) { |
| 293 | OptionDefinitionPtr def = parser.parse(option_def); |
| 294 | try { |
| 295 | storage->add(def); |
| 296 | } catch (const std::exception& ex) { |
| 297 | // Append position if there is a failure. |
| 298 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << option_def->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 299, oss__.str().c_str()); } while (1) |
| 299 | << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << option_def->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 299, oss__.str().c_str()); } while (1); |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | // All definitions have been prepared. Put them as runtime options into |
| 304 | // the libdhcp++. |
| 305 | LibDHCP::setRuntimeOptionDefs(storage->getContainer()); |
| 306 | } |
| 307 | |
| 308 | //****************************** RelayInfoParser ******************************** |
| 309 | RelayInfoParser::RelayInfoParser(const Option::Universe& family) |
| 310 | : family_(family) { |
| 311 | }; |
| 312 | |
| 313 | void |
| 314 | RelayInfoParser::parse(const isc::dhcp::Network::RelayInfoPtr& relay_info, |
| 315 | ConstElementPtr relay_elem) { |
| 316 | |
| 317 | if (relay_elem->getType() != Element::map) { |
| 318 | isc_throw(DhcpConfigError, "relay must be a map")do { std::ostringstream oss__; oss__ << "relay must be a map" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 318, oss__.str().c_str()); } while (1); |
| 319 | } |
| 320 | |
| 321 | ConstElementPtr addresses = relay_elem->get("ip-addresses"); |
| 322 | if (!addresses) { |
| 323 | isc_throw(DhcpConfigError, "ip-addresses is required")do { std::ostringstream oss__; oss__ << "ip-addresses is required" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 323, oss__.str().c_str()); } while (1); |
| 324 | } |
| 325 | |
| 326 | // Create our resultant RelayInfo structure |
| 327 | *relay_info = isc::dhcp::Network::RelayInfo(); |
| 328 | |
| 329 | if (addresses->getType() != Element::list) { |
| 330 | isc_throw(DhcpConfigError, "ip-addresses must be a list "do { std::ostringstream oss__; oss__ << "ip-addresses must be a list " "(" << getPosition("ip-addresses", relay_elem) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 331, oss__.str().c_str()); } while (1) |
| 331 | "(" << getPosition("ip-addresses", relay_elem) << ")")do { std::ostringstream oss__; oss__ << "ip-addresses must be a list " "(" << getPosition("ip-addresses", relay_elem) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 331, oss__.str().c_str()); } while (1); |
| 332 | } |
| 333 | |
| 334 | for (auto const& address_element : addresses->listValue()) { |
| 335 | addAddress("ip-addresses", address_element->stringValue(), |
| 336 | relay_elem, relay_info); |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | void |
| 341 | RelayInfoParser::addAddress(const std::string& name, |
| 342 | const std::string& address_str, |
| 343 | ConstElementPtr relay_elem, |
| 344 | const isc::dhcp::Network::RelayInfoPtr& relay_info) { |
| 345 | boost::scoped_ptr<isc::asiolink::IOAddress> ip; |
| 346 | try { |
| 347 | ip.reset(new isc::asiolink::IOAddress(address_str)); |
| 348 | } catch (const std::exception& ex) { |
| 349 | isc_throw(DhcpConfigError, "address " << address_strdo { std::ostringstream oss__; oss__ << "address " << address_str << " is not a valid: " << (family_ == Option::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 353, oss__ .str().c_str()); } while (1) |
| 350 | << " is not a valid: "do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a valid: " << (family_ == Option::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 353, oss__ .str().c_str()); } while (1) |
| 351 | << (family_ == Option::V4 ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a valid: " << (family_ == Option::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 353, oss__ .str().c_str()); } while (1) |
| 352 | << "address"do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a valid: " << (family_ == Option::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 353, oss__ .str().c_str()); } while (1) |
| 353 | << " (" << getPosition(name, relay_elem) << ")")do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a valid: " << (family_ == Option::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 353, oss__ .str().c_str()); } while (1); |
| 354 | } |
| 355 | |
| 356 | // Check if the address family matches. |
| 357 | if ((ip->isV4() && family_ != Option::V4) || |
| 358 | (ip->isV6() && family_ != Option::V6) ) { |
| 359 | isc_throw(DhcpConfigError, "address " << address_strdo { std::ostringstream oss__; oss__ << "address " << address_str << " is not a: " << (family_ == Option ::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 363, oss__ .str().c_str()); } while (1) |
| 360 | << " is not a: "do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a: " << (family_ == Option ::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 363, oss__ .str().c_str()); } while (1) |
| 361 | << (family_ == Option::V4 ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a: " << (family_ == Option ::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 363, oss__ .str().c_str()); } while (1) |
| 362 | << "address"do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a: " << (family_ == Option ::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 363, oss__ .str().c_str()); } while (1) |
| 363 | << " (" << getPosition(name, relay_elem) << ")")do { std::ostringstream oss__; oss__ << "address " << address_str << " is not a: " << (family_ == Option ::V4 ? "IPv4" : "IPv6") << "address" << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 363, oss__ .str().c_str()); } while (1); |
| 364 | } |
| 365 | |
| 366 | try { |
| 367 | relay_info->addAddress(*ip); |
| 368 | } catch (const std::exception& ex) { |
| 369 | isc_throw(DhcpConfigError, "cannot add address: " << address_strdo { std::ostringstream oss__; oss__ << "cannot add address: " << address_str << " to relay info: " << ex .what() << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 371, oss__.str().c_str()); } while (1) |
| 370 | << " to relay info: " << ex.what()do { std::ostringstream oss__; oss__ << "cannot add address: " << address_str << " to relay info: " << ex .what() << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 371, oss__.str().c_str()); } while (1) |
| 371 | << " (" << getPosition(name, relay_elem) << ")")do { std::ostringstream oss__; oss__ << "cannot add address: " << address_str << " to relay info: " << ex .what() << " (" << getPosition(name, relay_elem) << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 371, oss__.str().c_str()); } while (1); |
| 372 | } |
| 373 | } |
| 374 | |
| 375 | //****************************** PoolParser ******************************** |
| 376 | |
| 377 | void |
| 378 | PoolParser::parse(PoolStoragePtr pools, |
| 379 | ConstElementPtr pool_structure, |
| 380 | const uint16_t address_family, |
| 381 | bool encapsulate_options) { |
| 382 | |
| 383 | if (address_family == AF_INET2) { |
| 384 | checkKeywords(SimpleParser4::POOL4_PARAMETERS, pool_structure); |
| 385 | } else { |
| 386 | checkKeywords(SimpleParser6::POOL6_PARAMETERS, pool_structure); |
| 387 | } |
| 388 | |
| 389 | ConstElementPtr text_pool = pool_structure->get("pool"); |
| 390 | |
| 391 | if (!text_pool) { |
| 392 | isc_throw(DhcpConfigError, "Mandatory 'pool' entry missing in "do { std::ostringstream oss__; oss__ << "Mandatory 'pool' entry missing in " "definition: (" << pool_structure->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 393, oss__.str().c_str()); } while (1) |
| 393 | "definition: (" << pool_structure->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Mandatory 'pool' entry missing in " "definition: (" << pool_structure->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 393, oss__.str().c_str()); } while (1); |
| 394 | } |
| 395 | |
| 396 | // That should be a single pool representation. It should contain |
| 397 | // text is form prefix/len or first - last. Note that spaces |
| 398 | // are allowed |
| 399 | string txt = text_pool->stringValue(); |
| 400 | |
| 401 | // first let's remove any whitespaces |
| 402 | boost::erase_all(txt, " "); // space |
| 403 | boost::erase_all(txt, "\t"); // tabulation |
| 404 | |
| 405 | PoolPtr pool; |
| 406 | |
| 407 | // Is this prefix/len notation? |
| 408 | size_t pos = txt.find("/"); |
| 409 | if (pos != string::npos) { |
| 410 | isc::asiolink::IOAddress addr("::"); |
| 411 | uint8_t len = 0; |
| 412 | try { |
| 413 | addr = isc::asiolink::IOAddress(txt.substr(0, pos)); |
| 414 | |
| 415 | // start with the first character after / |
| 416 | string prefix_len = txt.substr(pos + 1); |
| 417 | |
| 418 | // It is lexical cast to int and then downcast to uint8_t. |
| 419 | // Direct cast to uint8_t (which is really an unsigned char) |
| 420 | // will result in interpreting the first digit as output |
| 421 | // value and throwing exception if length is written on two |
| 422 | // digits (because there are extra characters left over). |
| 423 | |
| 424 | // No checks for values over 128. Range correctness will |
| 425 | // be checked in Pool4 constructor, here we only check |
| 426 | // the representation fits in an uint8_t as this can't |
| 427 | // be done by a direct lexical cast as explained... |
| 428 | int val_len = boost::lexical_cast<int>(prefix_len); |
| 429 | if ((val_len < std::numeric_limits<uint8_t>::min()) || |
| 430 | (val_len > std::numeric_limits<uint8_t>::max())) { |
| 431 | // This exception will be handled 4 line later! |
| 432 | isc_throw(OutOfRange, "")do { std::ostringstream oss__; oss__ << ""; throw OutOfRange ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 432, oss__ .str().c_str()); } while (1); |
| 433 | } |
| 434 | len = static_cast<uint8_t>(val_len); |
| 435 | } catch (...) { |
| 436 | isc_throw(DhcpConfigError, "Failed to parse pool "do { std::ostringstream oss__; oss__ << "Failed to parse pool " "definition: " << txt << " (" << text_pool ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 438, oss__.str().c_str()); } while (1) |
| 437 | "definition: " << txt << " ("do { std::ostringstream oss__; oss__ << "Failed to parse pool " "definition: " << txt << " (" << text_pool ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 438, oss__.str().c_str()); } while (1) |
| 438 | << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to parse pool " "definition: " << txt << " (" << text_pool ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 438, oss__.str().c_str()); } while (1); |
| 439 | } |
| 440 | |
| 441 | try { |
| 442 | pool = poolMaker(addr, len); |
| 443 | pools->push_back(pool); |
| 444 | } catch (const std::exception& ex) { |
| 445 | isc_throw(DhcpConfigError, "Failed to create pool defined by: "do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: " << txt << " (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 446, oss__.str().c_str()); } while (1) |
| 446 | << txt << " (" << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: " << txt << " (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 446, oss__.str().c_str()); } while (1); |
| 447 | } |
| 448 | |
| 449 | } else { |
| 450 | isc::asiolink::IOAddress min("::"); |
| 451 | isc::asiolink::IOAddress max("::"); |
| 452 | |
| 453 | // Is this min-max notation? |
| 454 | pos = txt.find("-"); |
| 455 | if (pos != string::npos) { |
| 456 | // using min-max notation |
| 457 | try { |
| 458 | min = isc::asiolink::IOAddress(txt.substr(0, pos)); |
| 459 | max = isc::asiolink::IOAddress(txt.substr(pos + 1)); |
| 460 | } catch (...) { |
| 461 | isc_throw(DhcpConfigError, "Failed to parse pool "do { std::ostringstream oss__; oss__ << "Failed to parse pool " "definition: " << txt << " (" << text_pool ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 463, oss__.str().c_str()); } while (1) |
| 462 | "definition: " << txt << " ("do { std::ostringstream oss__; oss__ << "Failed to parse pool " "definition: " << txt << " (" << text_pool ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 463, oss__.str().c_str()); } while (1) |
| 463 | << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to parse pool " "definition: " << txt << " (" << text_pool ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 463, oss__.str().c_str()); } while (1); |
| 464 | } |
| 465 | |
| 466 | try { |
| 467 | pool = poolMaker(min, max); |
| 468 | pools->push_back(pool); |
| 469 | } catch (const std::exception& ex) { |
| 470 | isc_throw(DhcpConfigError, "Failed to create pool defined by: "do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: " << txt << " (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 471, oss__.str().c_str()); } while (1) |
| 471 | << txt << " (" << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: " << txt << " (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 471, oss__.str().c_str()); } while (1); |
| 472 | } |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | if (!pool) { |
| 477 | isc_throw(DhcpConfigError, "invalid pool definition: "do { std::ostringstream oss__; oss__ << "invalid pool definition: " << text_pool->stringValue() << ". There are two acceptable formats <min address-max address>" " or <prefix/len> (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 481, oss__.str().c_str()); } while (1) |
| 478 | << text_pool->stringValue() <<do { std::ostringstream oss__; oss__ << "invalid pool definition: " << text_pool->stringValue() << ". There are two acceptable formats <min address-max address>" " or <prefix/len> (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 481, oss__.str().c_str()); } while (1) |
| 479 | ". There are two acceptable formats <min address-max address>"do { std::ostringstream oss__; oss__ << "invalid pool definition: " << text_pool->stringValue() << ". There are two acceptable formats <min address-max address>" " or <prefix/len> (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 481, oss__.str().c_str()); } while (1) |
| 480 | " or <prefix/len> ("do { std::ostringstream oss__; oss__ << "invalid pool definition: " << text_pool->stringValue() << ". There are two acceptable formats <min address-max address>" " or <prefix/len> (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 481, oss__.str().c_str()); } while (1) |
| 481 | << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "invalid pool definition: " << text_pool->stringValue() << ". There are two acceptable formats <min address-max address>" " or <prefix/len> (" << text_pool->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 481, oss__.str().c_str()); } while (1); |
| 482 | } |
| 483 | |
| 484 | // If there is a pool-id, store it. |
| 485 | ConstElementPtr pool_id = pool_structure->get("pool-id"); |
| 486 | if (pool_id) { |
| 487 | if (pool_id->intValue() <= 0) { |
| 488 | isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a positive integer greater than 0" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 489, oss__.str().c_str()); } while (1) |
| 489 | << " a positive integer greater than 0")do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a positive integer greater than 0" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 489, oss__.str().c_str()); } while (1); |
| 490 | } else if (pool_id->intValue() > numeric_limits<uint32_t>::max()) { |
| 491 | isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a 32 bit unsigned integer" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 492, oss__.str().c_str()); } while (1) |
| 492 | << " a 32 bit unsigned integer")do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a 32 bit unsigned integer" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 492, oss__.str().c_str()); } while (1); |
| 493 | } |
| 494 | |
| 495 | pool->setID(pool_id->intValue()); |
| 496 | } |
| 497 | |
| 498 | // If there's user-context specified, store it. |
| 499 | ConstElementPtr user_context = pool_structure->get("user-context"); |
| 500 | if (user_context) { |
| 501 | // The grammar accepts only maps but still check it. |
| 502 | if (user_context->getType() != Element::map) { |
| 503 | isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("do { std::ostringstream oss__; oss__ << "User context has to be a map (" << user_context->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 504, oss__.str().c_str()); } while (1) |
| 504 | << user_context->getPosition() << ")")do { std::ostringstream oss__; oss__ << "User context has to be a map (" << user_context->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 504, oss__.str().c_str()); } while (1); |
| 505 | } |
| 506 | pool->setContext(user_context); |
| 507 | } |
| 508 | |
| 509 | // Parser pool specific options. |
| 510 | ConstElementPtr option_data = pool_structure->get("option-data"); |
| 511 | if (option_data) { |
| 512 | try { |
| 513 | CfgOptionPtr cfg = pool->getCfgOption(); |
| 514 | auto option_parser = createOptionDataListParser(address_family); |
| 515 | option_parser->parse(cfg, option_data, encapsulate_options); |
| 516 | } catch (const std::exception& ex) { |
| 517 | isc_throw(isc::dhcp::DhcpConfigError, ex.what()do { std::ostringstream oss__; oss__ << ex.what() << " (" << option_data->getPosition() << ")"; throw isc::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 518, oss__.str().c_str()); } while (1) |
| 518 | << " (" << option_data->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << option_data->getPosition() << ")"; throw isc::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 518, oss__.str().c_str()); } while (1); |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | // Client-class. |
| 523 | ConstElementPtr client_class = pool_structure->get("client-class"); |
| 524 | if (client_class) { |
| 525 | string cclass = client_class->stringValue(); |
| 526 | if (!cclass.empty()) { |
| 527 | pool->allowClientClass(cclass); |
| 528 | } |
| 529 | } |
| 530 | |
| 531 | // Setup client class list. |
| 532 | BaseNetworkParser::getClientClassesElem(pool_structure, |
| 533 | std::bind(&Pool::allowClientClass, |
| 534 | pool, ph::_1)); |
| 535 | |
| 536 | // Setup additional class list. |
| 537 | BaseNetworkParser::getAdditionalClassesElem(pool_structure, |
| 538 | std::bind(&Pool::addAdditionalClass, |
| 539 | pool, ph::_1)); |
| 540 | |
| 541 | // Parse DDNS behavioral parameters. |
| 542 | BaseNetworkParser parser; |
| 543 | parser.parseDdnsParameters(pool_structure, pool); |
| 544 | } |
| 545 | |
| 546 | boost::shared_ptr<OptionDataListParser> |
| 547 | PoolParser::createOptionDataListParser(const uint16_t address_family) const { |
| 548 | return (boost::make_shared<OptionDataListParser>(address_family)); |
| 549 | } |
| 550 | |
| 551 | //****************************** Pool4Parser ************************* |
| 552 | |
| 553 | PoolPtr |
| 554 | Pool4Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t) { |
| 555 | return (PoolPtr(new Pool4(addr, len))); |
| 556 | } |
| 557 | |
| 558 | PoolPtr |
| 559 | Pool4Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t) { |
| 560 | return (PoolPtr(new Pool4(min, max))); |
| 561 | } |
| 562 | |
| 563 | //****************************** Pools4ListParser ************************* |
| 564 | |
| 565 | void |
| 566 | Pools4ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list, |
| 567 | bool encapsulate_options) { |
| 568 | for (auto const& pool : pools_list->listValue()) { |
| 569 | auto const& parser = createPoolConfigParser(); |
| 570 | parser->parse(pools, pool, AF_INET2, encapsulate_options); |
| 571 | } |
| 572 | } |
| 573 | |
| 574 | boost::shared_ptr<PoolParser> |
| 575 | Pools4ListParser::createPoolConfigParser() const { |
| 576 | return (boost::make_shared<Pool4Parser>()); |
| 577 | } |
| 578 | |
| 579 | //****************************** SubnetConfigParser ************************* |
| 580 | |
| 581 | SubnetConfigParser::SubnetConfigParser(uint16_t family, bool check_iface) |
| 582 | : pools_(new PoolStorage()), |
| 583 | address_family_(family), |
| 584 | check_iface_(check_iface) { |
| 585 | relay_info_.reset(new isc::dhcp::Network::RelayInfo()); |
| 586 | } |
| 587 | |
| 588 | SubnetPtr |
| 589 | SubnetConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) { |
| 590 | |
| 591 | ConstElementPtr relay_params = subnet->get("relay"); |
| 592 | if (relay_params) { |
| 593 | Option::Universe u = (address_family_ == AF_INET2) ? Option::V4 : Option::V6; |
| 594 | RelayInfoParser parser(u); |
| 595 | parser.parse(relay_info_, relay_params); |
| 596 | } |
| 597 | |
| 598 | // Create a subnet. |
| 599 | try { |
| 600 | createSubnet(subnet); |
| 601 | } catch (const std::exception& ex) { |
| 602 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "subnet configuration failed: " << ex.what(); throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 603, oss__.str().c_str()); } while (1) |
| 603 | "subnet configuration failed: " << ex.what())do { std::ostringstream oss__; oss__ << "subnet configuration failed: " << ex.what(); throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 603, oss__.str().c_str()); } while (1); |
| 604 | } |
| 605 | |
| 606 | // We create subnet first and then parse the options straight into the subnet's |
| 607 | // CfgOption structure. Previously, we first parsed the options and then copied |
| 608 | // them into the CfgOption after creating the subnet but it had two issues. First, |
| 609 | // it cost performance. Second, copying options reset the isEncapsulated() flag. |
| 610 | // If the options have been encapsulated we want to preserve the flag to ensure |
| 611 | // they are not encapsulated several times. |
| 612 | ConstElementPtr options_params = subnet->get("option-data"); |
| 613 | if (options_params) { |
| 614 | auto opt_parser = createOptionDataListParser(); |
| 615 | opt_parser->parse(subnet_->getCfgOption(), options_params, encapsulate_options); |
| 616 | } |
| 617 | |
| 618 | return (subnet_); |
| 619 | } |
| 620 | |
| 621 | void |
| 622 | SubnetConfigParser::createSubnet(ConstElementPtr params) { |
| 623 | std::string subnet_txt; |
| 624 | try { |
| 625 | subnet_txt = getString(params, "subnet"); |
| 626 | } catch (const DhcpConfigError &) { |
| 627 | // rethrow with precise error |
| 628 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "mandatory 'subnet' parameter is missing for a subnet being" " configured (" << params->getPosition() << ")" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 630, oss__.str().c_str()); } while (1) |
| 629 | "mandatory 'subnet' parameter is missing for a subnet being"do { std::ostringstream oss__; oss__ << "mandatory 'subnet' parameter is missing for a subnet being" " configured (" << params->getPosition() << ")" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 630, oss__.str().c_str()); } while (1) |
| 630 | " configured (" << params->getPosition() << ")")do { std::ostringstream oss__; oss__ << "mandatory 'subnet' parameter is missing for a subnet being" " configured (" << params->getPosition() << ")" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 630, oss__.str().c_str()); } while (1); |
| 631 | } |
| 632 | |
| 633 | // Remove any spaces or tabs. |
| 634 | boost::erase_all(subnet_txt, " "); |
| 635 | boost::erase_all(subnet_txt, "\t"); |
| 636 | |
| 637 | // The subnet format is prefix/len. We are going to extract |
| 638 | // the prefix portion of a subnet string to create IOAddress |
| 639 | // object from it. IOAddress will be passed to the Subnet's |
| 640 | // constructor later on. In order to extract the prefix we |
| 641 | // need to get all characters preceding "/". |
| 642 | size_t pos = subnet_txt.find("/"); |
| 643 | if (pos == string::npos) { |
| 644 | ConstElementPtr elem = params->get("subnet"); |
| 645 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Invalid subnet syntax (prefix/len expected):" << subnet_txt << " (" << elem->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 647, oss__.str().c_str()); } while (1) |
| 646 | "Invalid subnet syntax (prefix/len expected):" << subnet_txtdo { std::ostringstream oss__; oss__ << "Invalid subnet syntax (prefix/len expected):" << subnet_txt << " (" << elem->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 647, oss__.str().c_str()); } while (1) |
| 647 | << " (" << elem->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Invalid subnet syntax (prefix/len expected):" << subnet_txt << " (" << elem->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 647, oss__.str().c_str()); } while (1); |
| 648 | } |
| 649 | |
| 650 | // Try to create the address object. It also validates that |
| 651 | // the address syntax is ok. |
| 652 | isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos)); |
| 653 | |
| 654 | // Now parse out the prefix length. |
| 655 | unsigned int len; |
| 656 | try { |
| 657 | len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1)); |
| 658 | } catch (const boost::bad_lexical_cast&) { |
| 659 | ConstElementPtr elem = params->get("subnet"); |
| 660 | isc_throw(DhcpConfigError, "prefix length: '" <<do { std::ostringstream oss__; oss__ << "prefix length: '" << subnet_txt.substr(pos+1) << "' is not an integer (" << elem->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 662, oss__ .str().c_str()); } while (1) |
| 661 | subnet_txt.substr(pos+1) << "' is not an integer ("do { std::ostringstream oss__; oss__ << "prefix length: '" << subnet_txt.substr(pos+1) << "' is not an integer (" << elem->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 662, oss__ .str().c_str()); } while (1) |
| 662 | << elem->getPosition() << ")")do { std::ostringstream oss__; oss__ << "prefix length: '" << subnet_txt.substr(pos+1) << "' is not an integer (" << elem->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 662, oss__ .str().c_str()); } while (1); |
| 663 | } |
| 664 | |
| 665 | // Sanity check the prefix length |
| 666 | if ((addr.isV6() && len > 128) || |
| 667 | (addr.isV4() && len > 32)) { |
| 668 | ConstElementPtr elem = params->get("subnet"); |
| 669 | isc_throw(BadValue,do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: " << len << " (" << elem->getPosition() << ")"; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 671, oss__.str().c_str()); } while (1) |
| 670 | "Invalid prefix length specified for subnet: " << lendo { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: " << len << " (" << elem->getPosition() << ")"; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 671, oss__.str().c_str()); } while (1) |
| 671 | << " (" << elem->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: " << len << " (" << elem->getPosition() << ")"; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 671, oss__.str().c_str()); } while (1); |
| 672 | } |
| 673 | |
| 674 | // Call the subclass's method to instantiate the subnet |
| 675 | initSubnet(params, addr, len); |
| 676 | |
| 677 | // Add pools to it. |
| 678 | for (auto const& pool : *pools_) { |
| 679 | try { |
| 680 | subnet_->addPool(pool); |
| 681 | } catch (const BadValue& ex) { |
| 682 | // addPool() can throw BadValue if the pool is overlapping or |
| 683 | // is out of bounds for the subnet. |
| 684 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << ex.what() << " (" << params->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 685, oss__ .str().c_str()); } while (1) |
| 685 | ex.what() << " (" << params->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << params->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 685, oss__ .str().c_str()); } while (1); |
| 686 | } |
| 687 | } |
| 688 | // If there's user-context specified, store it. |
| 689 | ConstElementPtr user_context = params->get("user-context"); |
| 690 | if (user_context) { |
| 691 | // The grammar accepts only maps but still check it. |
| 692 | if (user_context->getType() != Element::map) { |
| 693 | isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("do { std::ostringstream oss__; oss__ << "User context has to be a map (" << user_context->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 694, oss__.str().c_str()); } while (1) |
| 694 | << user_context->getPosition() << ")")do { std::ostringstream oss__; oss__ << "User context has to be a map (" << user_context->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 694, oss__.str().c_str()); } while (1); |
| 695 | } |
| 696 | subnet_->setContext(user_context); |
| 697 | } |
| 698 | |
| 699 | // In order to take advantage of the dynamic inheritance of global |
| 700 | // parameters to a subnet we need to set a callback function for each |
| 701 | // subnet to allow for fetching global parameters. |
| 702 | subnet_->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr { |
| 703 | return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals()); |
| 704 | }); |
| 705 | } |
| 706 | |
| 707 | boost::shared_ptr<OptionDataListParser> |
| 708 | SubnetConfigParser::createOptionDataListParser() const { |
| 709 | return (boost::make_shared<OptionDataListParser>(address_family_)); |
| 710 | } |
| 711 | |
| 712 | //****************************** Subnet4ConfigParser ************************* |
| 713 | |
| 714 | Subnet4ConfigParser::Subnet4ConfigParser(bool check_iface) |
| 715 | : SubnetConfigParser(AF_INET2, check_iface) { |
| 716 | } |
| 717 | |
| 718 | Subnet4Ptr |
| 719 | Subnet4ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) { |
| 720 | // Check parameters. |
| 721 | checkKeywords(SimpleParser4::SUBNET4_PARAMETERS, subnet); |
| 722 | |
| 723 | /// Parse Pools first. |
| 724 | ConstElementPtr pools = subnet->get("pools"); |
| 725 | if (pools) { |
| 726 | auto const& parser = createPoolsListParser(); |
| 727 | parser->parse(pools_, pools, encapsulate_options); |
| 728 | } |
| 729 | |
| 730 | SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options); |
| 731 | |
| 732 | if (!generic) { |
| 733 | // Sanity check: not supposed to fail. |
| 734 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Failed to create an IPv4 subnet (" << subnet->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 736, oss__ .str().c_str()); } while (1) |
| 735 | "Failed to create an IPv4 subnet (" <<do { std::ostringstream oss__; oss__ << "Failed to create an IPv4 subnet (" << subnet->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 736, oss__ .str().c_str()); } while (1) |
| 736 | subnet->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create an IPv4 subnet (" << subnet->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 736, oss__ .str().c_str()); } while (1); |
| 737 | } |
| 738 | |
| 739 | Subnet4Ptr sn4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_); |
| 740 | if (!sn4ptr) { |
| 741 | // If we hit this, it is a programming error. |
| 742 | isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "Invalid Subnet4 cast in Subnet4ConfigParser::parse" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 743, oss__.str().c_str()); } while (1) |
| 743 | "Invalid Subnet4 cast in Subnet4ConfigParser::parse")do { std::ostringstream oss__; oss__ << "Invalid Subnet4 cast in Subnet4ConfigParser::parse" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 743, oss__.str().c_str()); } while (1); |
| 744 | } |
| 745 | |
| 746 | // Set relay information if it was parsed |
| 747 | if (relay_info_) { |
| 748 | sn4ptr->setRelayInfo(*relay_info_); |
| 749 | } |
| 750 | |
| 751 | // Parse Host Reservations for this subnet if any. |
| 752 | ConstElementPtr reservations = subnet->get("reservations"); |
| 753 | if (reservations) { |
| 754 | HostCollection hosts; |
| 755 | HostReservationsListParser<HostReservationParser4> parser; |
| 756 | parser.parse(subnet_->getID(), reservations, hosts); |
| 757 | for (auto const& h : hosts) { |
| 758 | validateResv(sn4ptr, h); |
| 759 | CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h); |
| 760 | } |
| 761 | } |
| 762 | |
| 763 | // Parse allocator specification. |
| 764 | auto network4 = boost::dynamic_pointer_cast<Network>(sn4ptr); |
| 765 | parseAllocatorParams(subnet, network4); |
| 766 | |
| 767 | // Instantiate the allocator. |
| 768 | sn4ptr->createAllocators(); |
| 769 | |
| 770 | return (sn4ptr); |
| 771 | } |
| 772 | |
| 773 | void |
| 774 | Subnet4ConfigParser::initSubnet(data::ConstElementPtr params, |
| 775 | asiolink::IOAddress addr, uint8_t len) { |
| 776 | // Subnet ID is required and must be in 1..SUBNET_ID_MAX. |
| 777 | int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX); |
| 778 | SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1, |
| 779 | subnet_id_max)); |
| 780 | |
| 781 | auto subnet4 = Subnet4::create(addr, len, Triplet<uint32_t>(), |
| 782 | Triplet<uint32_t>(), Triplet<uint32_t>(), |
| 783 | subnet_id); |
| 784 | subnet_ = subnet4; |
| 785 | |
| 786 | ElementPtr mutable_params; |
| 787 | mutable_params = boost::const_pointer_cast<Element>(params); |
| 788 | |
| 789 | // Parse parameters common to all Network derivations. |
| 790 | NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet4); |
| 791 | parseCommon(mutable_params, network); |
| 792 | |
| 793 | std::ostringstream output; |
| 794 | output << addr << "/" << static_cast<int>(len) << " with params: "; |
| 795 | |
| 796 | bool has_renew = !subnet4->getT1().unspecified(); |
| 797 | bool has_rebind = !subnet4->getT2().unspecified(); |
| 798 | int64_t renew = -1; |
| 799 | int64_t rebind = -1; |
| 800 | |
| 801 | // t1 and t2 are optional may be not specified. |
| 802 | if (has_renew) { |
| 803 | renew = subnet4->getT1().get(); |
| 804 | output << "t1=" << renew << ", "; |
| 805 | } |
| 806 | if (has_rebind) { |
| 807 | rebind = subnet4->getT2().get(); |
| 808 | output << "t2=" << rebind << ", "; |
| 809 | } |
| 810 | |
| 811 | if (!subnet4->getValid().unspecified()) { |
| 812 | output << "valid-lifetime=" << subnet4->getValid().get(); |
| 813 | } |
| 814 | |
| 815 | LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_NEW_SUBNET4)if (!(dhcpsrv_logger).isInfoEnabled()) { } else (dhcpsrv_logger ).info((DHCPSRV_CFGMGR_NEW_SUBNET4)).arg(output.str()); |
| 816 | |
| 817 | // Set the match-client-id value for the subnet. |
| 818 | if (params->contains("match-client-id")) { |
| 819 | bool match_client_id = getBoolean(params, "match-client-id"); |
| 820 | subnet4->setMatchClientId(match_client_id); |
| 821 | } |
| 822 | |
| 823 | // Set the authoritative value for the subnet. |
| 824 | if (params->contains("authoritative")) { |
| 825 | bool authoritative = getBoolean(params, "authoritative"); |
| 826 | subnet4->setAuthoritative(authoritative); |
| 827 | } |
| 828 | |
| 829 | // Set next-server. The default value is 0.0.0.0. Nevertheless, the |
| 830 | // user could have messed that up by specifying incorrect value. |
| 831 | // To avoid using 0.0.0.0, user can specify "". |
| 832 | if (params->contains("next-server")) { |
| 833 | string next_server; |
| 834 | try { |
| 835 | next_server = getString(params, "next-server"); |
| 836 | if (!next_server.empty()) { |
| 837 | subnet4->setSiaddr(IOAddress(next_server)); |
| 838 | } |
| 839 | } catch (...) { |
| 840 | ConstElementPtr next = params->get("next-server"); |
| 841 | string pos; |
| 842 | if (next) { |
| 843 | pos = next->getPosition().str(); |
| 844 | } else { |
| 845 | pos = params->getPosition().str(); |
| 846 | } |
| 847 | isc_throw(DhcpConfigError, "invalid parameter next-server : "do { std::ostringstream oss__; oss__ << "invalid parameter next-server : " << next_server << "(" << pos << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 848, oss__.str().c_str()); } while (1) |
| 848 | << next_server << "(" << pos << ")")do { std::ostringstream oss__; oss__ << "invalid parameter next-server : " << next_server << "(" << pos << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 848, oss__.str().c_str()); } while (1); |
| 849 | } |
| 850 | } |
| 851 | |
| 852 | // Set server-hostname. |
| 853 | if (params->contains("server-hostname")) { |
| 854 | std::string sname = getString(params, "server-hostname"); |
| 855 | if (!sname.empty()) { |
| 856 | if (sname.length() >= Pkt4::MAX_SNAME_LEN) { |
| 857 | ConstElementPtr error = params->get("server-hostname"); |
| 858 | isc_throw(DhcpConfigError, "server-hostname must be at most "do { std::ostringstream oss__; oss__ << "server-hostname must be at most " << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is " << sname.length() << " (" << error->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 861, oss__.str().c_str()); } while (1) |
| 859 | << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "do { std::ostringstream oss__; oss__ << "server-hostname must be at most " << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is " << sname.length() << " (" << error->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 861, oss__.str().c_str()); } while (1) |
| 860 | << sname.length() << " ("do { std::ostringstream oss__; oss__ << "server-hostname must be at most " << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is " << sname.length() << " (" << error->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 861, oss__.str().c_str()); } while (1) |
| 861 | << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "server-hostname must be at most " << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is " << sname.length() << " (" << error->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 861, oss__.str().c_str()); } while (1); |
| 862 | } |
| 863 | subnet4->setSname(sname); |
| 864 | } |
| 865 | } |
| 866 | |
| 867 | // Set boot-file-name. |
| 868 | if (params->contains("boot-file-name")) { |
| 869 | std::string filename =getString(params, "boot-file-name"); |
| 870 | if (!filename.empty()) { |
| 871 | if (filename.length() > Pkt4::MAX_FILE_LEN) { |
| 872 | ConstElementPtr error = params->get("boot-file-name"); |
| 873 | isc_throw(DhcpConfigError, "boot-file-name must be at most "do { std::ostringstream oss__; oss__ << "boot-file-name must be at most " << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is " << filename.length() << " (" << error-> getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 876, oss__.str().c_str()); } while (1) |
| 874 | << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "do { std::ostringstream oss__; oss__ << "boot-file-name must be at most " << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is " << filename.length() << " (" << error-> getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 876, oss__.str().c_str()); } while (1) |
| 875 | << filename.length() << " ("do { std::ostringstream oss__; oss__ << "boot-file-name must be at most " << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is " << filename.length() << " (" << error-> getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 876, oss__.str().c_str()); } while (1) |
| 876 | << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "boot-file-name must be at most " << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is " << filename.length() << " (" << error-> getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 876, oss__.str().c_str()); } while (1); |
| 877 | } |
| 878 | subnet4->setFilename(filename); |
| 879 | } |
| 880 | } |
| 881 | |
| 882 | // Get interface name. If it is defined, then the subnet is available |
| 883 | // directly over specified network interface. |
| 884 | if (params->contains("interface")) { |
| 885 | std::string iface = getString(params, "interface"); |
| 886 | if (!iface.empty()) { |
| 887 | if (check_iface_ && !IfaceMgr::instance().getIface(iface)) { |
| 888 | ConstElementPtr error = params->get("interface"); |
| 889 | isc_throw(DhcpConfigError, "Specified network interface name " << ifacedo { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet4-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 892, oss__.str().c_str()); } while (1) |
| 890 | << " for subnet " << subnet4->toText()do { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet4-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 892, oss__.str().c_str()); } while (1) |
| 891 | << " is not present in the system ("do { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet4-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 892, oss__.str().c_str()); } while (1) |
| 892 | << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet4-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 892, oss__.str().c_str()); } while (1); |
| 893 | } |
| 894 | |
| 895 | subnet4->setIface(iface); |
| 896 | } |
| 897 | } |
| 898 | |
| 899 | // Try setting up client class. |
| 900 | if (params->contains("client-class")) { |
| 901 | string client_class = getString(params, "client-class"); |
| 902 | if (!client_class.empty()) { |
| 903 | subnet4->allowClientClass(client_class); |
| 904 | } |
| 905 | } |
| 906 | |
| 907 | // Setup client class list. |
| 908 | getClientClassesElem(params, std::bind(&Network::allowClientClass, |
| 909 | boost::dynamic_pointer_cast<Network>(subnet4), ph::_1)); |
| 910 | |
| 911 | // Setup additional class list. |
| 912 | getAdditionalClassesElem(params, std::bind(&Network::addAdditionalClass, |
| 913 | boost::dynamic_pointer_cast<Network>(subnet4), ph::_1)); |
| 914 | |
| 915 | // 4o6 specific parameter: 4o6-interface. |
| 916 | if (params->contains("4o6-interface")) { |
| 917 | string iface4o6 = getString(params, "4o6-interface"); |
| 918 | if (!iface4o6.empty()) { |
| 919 | subnet4->get4o6().setIface4o6(iface4o6); |
| 920 | subnet4->get4o6().enabled(true); |
| 921 | } |
| 922 | } |
| 923 | |
| 924 | // 4o6 specific parameter: 4o6-subnet. |
| 925 | if (params->contains("4o6-subnet")) { |
| 926 | string subnet4o6 = getString(params, "4o6-subnet"); |
| 927 | if (!subnet4o6.empty()) { |
| 928 | size_t slash = subnet4o6.find("/"); |
| 929 | if (slash == std::string::npos) { |
| 930 | isc_throw(DhcpConfigError, "Missing / in the 4o6-subnet parameter:"do { std::ostringstream oss__; oss__ << "Missing / in the 4o6-subnet parameter:" << subnet4o6 << ", expected format: prefix6/length" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 931, oss__.str().c_str()); } while (1) |
| 931 | << subnet4o6 << ", expected format: prefix6/length")do { std::ostringstream oss__; oss__ << "Missing / in the 4o6-subnet parameter:" << subnet4o6 << ", expected format: prefix6/length" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 931, oss__.str().c_str()); } while (1); |
| 932 | } |
| 933 | string prefix = subnet4o6.substr(0, slash); |
| 934 | string lenstr = subnet4o6.substr(slash + 1); |
| 935 | |
| 936 | len = 128; |
Value stored to 'len' is never read | |
| 937 | try { |
| 938 | len = boost::lexical_cast<unsigned int>(lenstr.c_str()); |
| 939 | } catch (const boost::bad_lexical_cast &) { |
| 940 | isc_throw(DhcpConfigError, "Invalid prefix length specified in "do { std::ostringstream oss__; oss__ << "Invalid prefix length specified in " "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 941, oss__.str().c_str()); } while (1) |
| 941 | "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value")do { std::ostringstream oss__; oss__ << "Invalid prefix length specified in " "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 941, oss__.str().c_str()); } while (1); |
| 942 | } |
| 943 | subnet4->get4o6().setSubnet4o6(IOAddress(prefix), len); |
| 944 | subnet4->get4o6().enabled(true); |
| 945 | } |
| 946 | } |
| 947 | |
| 948 | // Try 4o6 specific parameter: 4o6-interface-id |
| 949 | if (params->contains("4o6-interface-id")) { |
| 950 | std::string ifaceid = getString(params, "4o6-interface-id"); |
| 951 | if (!ifaceid.empty()) { |
| 952 | OptionBuffer tmp(ifaceid.begin(), ifaceid.end()); |
| 953 | OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); |
| 954 | subnet4->get4o6().setInterfaceId(opt); |
| 955 | subnet4->get4o6().enabled(true); |
| 956 | } |
| 957 | } |
| 958 | |
| 959 | /// client-class processing is now generic and handled in the common |
| 960 | /// code (see isc::data::SubnetConfigParser::createSubnet) |
| 961 | |
| 962 | // Here globally defined options were merged to the subnet specific |
| 963 | // options but this is no longer the case (they have a different |
| 964 | // and not consecutive priority). |
| 965 | |
| 966 | // Parse t1-percent and t2-percent |
| 967 | parseTeePercents(params, network); |
| 968 | |
| 969 | // Parse DDNS parameters |
| 970 | parseDdnsParams(params, network); |
| 971 | |
| 972 | // Parse lease cache parameters |
| 973 | parseCacheParams(params, network); |
| 974 | |
| 975 | // Parse adaptive lease time parameter. |
| 976 | parseAdaptiveLeaseTimeParam(params, network); |
| 977 | |
| 978 | // Set the offer_lft value for the subnet. |
| 979 | if (params->contains("offer-lifetime")) { |
| 980 | uint32_t offer_lft = getInteger(params, "offer-lifetime"); |
| 981 | subnet4->setOfferLft(offer_lft); |
| 982 | } |
| 983 | |
| 984 | // Parse offer-lifetime parameter. |
| 985 | Network4Ptr network4 = boost::dynamic_pointer_cast<Network4>(subnet4); |
| 986 | parseOfferLft(params, network4); |
| 987 | |
| 988 | } |
| 989 | |
| 990 | void |
| 991 | Subnet4ConfigParser::validateResv(const Subnet4Ptr& subnet, ConstHostPtr host) { |
| 992 | const IOAddress& address = host->getIPv4Reservation(); |
| 993 | if (!address.isV4Zero() && !subnet->inRange(address)) { |
| 994 | isc_throw(DhcpConfigError, "specified reservation '" << addressdo { std::ostringstream oss__; oss__ << "specified reservation '" << address << "' is not within the IPv4 subnet '" << subnet->toText() << "'"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 996, oss__ .str().c_str()); } while (1) |
| 995 | << "' is not within the IPv4 subnet '"do { std::ostringstream oss__; oss__ << "specified reservation '" << address << "' is not within the IPv4 subnet '" << subnet->toText() << "'"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 996, oss__ .str().c_str()); } while (1) |
| 996 | << subnet->toText() << "'")do { std::ostringstream oss__; oss__ << "specified reservation '" << address << "' is not within the IPv4 subnet '" << subnet->toText() << "'"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 996, oss__ .str().c_str()); } while (1); |
| 997 | } |
| 998 | } |
| 999 | |
| 1000 | boost::shared_ptr<PoolsListParser> |
| 1001 | Subnet4ConfigParser::createPoolsListParser() const { |
| 1002 | return (boost::make_shared<Pools4ListParser>()); |
| 1003 | } |
| 1004 | |
| 1005 | //**************************** Subnets4ListConfigParser ********************** |
| 1006 | |
| 1007 | Subnets4ListConfigParser::Subnets4ListConfigParser(bool check_iface) |
| 1008 | : check_iface_(check_iface) { |
| 1009 | } |
| 1010 | |
| 1011 | size_t |
| 1012 | Subnets4ListConfigParser::parse(SrvConfigPtr cfg, |
| 1013 | ConstElementPtr subnets_list, |
| 1014 | bool encapsulate_options) { |
| 1015 | size_t cnt = 0; |
| 1016 | for (auto const& subnet_json : subnets_list->listValue()) { |
| 1017 | |
| 1018 | auto const& parser = createSubnetConfigParser(); |
| 1019 | Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options); |
| 1020 | if (subnet) { |
| 1021 | |
| 1022 | // Adding a subnet to the Configuration Manager may fail if the |
| 1023 | // subnet id is invalid (duplicate). Thus, we catch exceptions |
| 1024 | // here to append a position in the configuration string. |
| 1025 | try { |
| 1026 | cfg->getCfgSubnets4()->add(subnet); |
| 1027 | cnt++; |
| 1028 | } catch (const std::exception& ex) { |
| 1029 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1030, oss__.str().c_str()); } while (1) |
| 1030 | << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1030, oss__.str().c_str()); } while (1); |
| 1031 | } |
| 1032 | } |
| 1033 | } |
| 1034 | return (cnt); |
| 1035 | } |
| 1036 | |
| 1037 | size_t |
| 1038 | Subnets4ListConfigParser::parse(Subnet4Collection& subnets, |
| 1039 | data::ConstElementPtr subnets_list, |
| 1040 | bool encapsulate_options) { |
| 1041 | size_t cnt = 0; |
| 1042 | for (auto const& subnet_json : subnets_list->listValue()) { |
| 1043 | |
| 1044 | auto const& parser = createSubnetConfigParser(); |
| 1045 | Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options); |
| 1046 | if (subnet) { |
| 1047 | try { |
| 1048 | auto ret = subnets.insert(subnet); |
| 1049 | if (!ret.second) { |
| 1050 | isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1051, oss__.str().c_str()); } while (1) |
| 1051 | "can't store subnet because of conflict")do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1051, oss__.str().c_str()); } while (1); |
| 1052 | } |
| 1053 | ++cnt; |
| 1054 | } catch (const std::exception& ex) { |
| 1055 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1056, oss__.str().c_str()); } while (1) |
| 1056 | << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1056, oss__.str().c_str()); } while (1); |
| 1057 | } |
| 1058 | } |
| 1059 | } |
| 1060 | return (cnt); |
| 1061 | } |
| 1062 | |
| 1063 | boost::shared_ptr<Subnet4ConfigParser> |
| 1064 | Subnets4ListConfigParser::createSubnetConfigParser() const { |
| 1065 | return (boost::make_shared<Subnet4ConfigParser>(check_iface_)); |
| 1066 | } |
| 1067 | |
| 1068 | //**************************** Pool6Parser ********************************* |
| 1069 | |
| 1070 | PoolPtr |
| 1071 | Pool6Parser::poolMaker(IOAddress &addr, uint32_t len, int32_t ptype) |
| 1072 | { |
| 1073 | return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type> |
| 1074 | (ptype), addr, len))); |
| 1075 | } |
| 1076 | |
| 1077 | PoolPtr |
| 1078 | Pool6Parser::poolMaker(IOAddress &min, IOAddress &max, int32_t ptype) |
| 1079 | { |
| 1080 | return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type> |
| 1081 | (ptype), min, max))); |
| 1082 | } |
| 1083 | |
| 1084 | |
| 1085 | //**************************** Pool6ListParser *************************** |
| 1086 | |
| 1087 | void |
| 1088 | Pools6ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list, |
| 1089 | bool encapsulate_options) { |
| 1090 | for (auto const& pool : pools_list->listValue()) { |
| 1091 | auto const& parser = createPoolConfigParser(); |
| 1092 | parser->parse(pools, pool, AF_INET610, encapsulate_options); |
| 1093 | } |
| 1094 | } |
| 1095 | |
| 1096 | boost::shared_ptr<PoolParser> |
| 1097 | Pools6ListParser::createPoolConfigParser() const { |
| 1098 | return (boost::make_shared<Pool6Parser>()); |
| 1099 | } |
| 1100 | |
| 1101 | //**************************** PdPoolParser ****************************** |
| 1102 | |
| 1103 | PdPoolParser::PdPoolParser() { |
| 1104 | } |
| 1105 | |
| 1106 | void |
| 1107 | PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool, |
| 1108 | bool encapsulate_options) { |
| 1109 | checkKeywords(SimpleParser6::PD_POOL6_PARAMETERS, pd_pool); |
| 1110 | |
| 1111 | std::string addr_str = getString(pd_pool, "prefix"); |
| 1112 | |
| 1113 | uint8_t prefix_len = getUint8(pd_pool, "prefix-len"); |
| 1114 | |
| 1115 | uint8_t delegated_len = getUint8(pd_pool, "delegated-len"); |
| 1116 | |
| 1117 | std::string excluded_prefix_str = "::"; |
| 1118 | if (pd_pool->contains("excluded-prefix")) { |
| 1119 | excluded_prefix_str = getString(pd_pool, "excluded-prefix"); |
| 1120 | } |
| 1121 | |
| 1122 | uint8_t excluded_prefix_len = 0; |
| 1123 | if (pd_pool->contains("excluded-prefix-len")) { |
| 1124 | excluded_prefix_len = getUint8(pd_pool, "excluded-prefix-len"); |
| 1125 | } |
| 1126 | |
| 1127 | ConstElementPtr user_context = pd_pool->get("user-context"); |
| 1128 | if (user_context) { |
| 1129 | user_context_ = user_context; |
| 1130 | } |
| 1131 | |
| 1132 | ConstElementPtr client_class = pd_pool->get("client-class"); |
| 1133 | if (client_class) { |
| 1134 | client_class_ = client_class; |
| 1135 | } |
| 1136 | |
| 1137 | // Check the pool parameters. It will throw an exception if any |
| 1138 | // of the required parameters are invalid. |
| 1139 | try { |
| 1140 | // Attempt to construct the local pool. |
| 1141 | pool_.reset(new Pool6(IOAddress(addr_str), |
| 1142 | prefix_len, |
| 1143 | delegated_len, |
| 1144 | IOAddress(excluded_prefix_str), |
| 1145 | excluded_prefix_len)); |
| 1146 | } catch (const std::exception& ex) { |
| 1147 | // Some parameters don't exist or are invalid. Since we are not |
| 1148 | // aware whether they don't exist or are invalid, let's append |
| 1149 | // the position of the pool map element. |
| 1150 | isc_throw(isc::dhcp::DhcpConfigError, ex.what()do { std::ostringstream oss__; oss__ << ex.what() << " (" << pd_pool->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1151, oss__.str().c_str()); } while (1) |
| 1151 | << " (" << pd_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << pd_pool->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1151, oss__.str().c_str()); } while (1); |
| 1152 | } |
| 1153 | |
| 1154 | // If there is a pool-id, store it. |
| 1155 | ConstElementPtr pool_id = pd_pool->get("pool-id"); |
| 1156 | if (pool_id) { |
| 1157 | if (pool_id->intValue() <= 0) { |
| 1158 | isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a positive integer greater than 0" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1159, oss__.str().c_str()); } while (1) |
| 1159 | << " a positive integer greater than 0")do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a positive integer greater than 0" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1159, oss__.str().c_str()); } while (1); |
| 1160 | } else if (pool_id->intValue() > numeric_limits<uint32_t>::max()) { |
| 1161 | isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a 32 bit unsigned integer" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1162, oss__.str().c_str()); } while (1) |
| 1162 | << " a 32 bit unsigned integer")do { std::ostringstream oss__; oss__ << "pool-id " << pool_id->intValue() << " is not" << " a 32 bit unsigned integer" ; throw BadValue("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1162, oss__.str().c_str()); } while (1); |
| 1163 | } |
| 1164 | |
| 1165 | pool_->setID(pool_id->intValue()); |
| 1166 | } |
| 1167 | |
| 1168 | // We create subnet first and then parse the options straight into the subnet's |
| 1169 | // CfgOption structure. Previously, we first parsed the options and then copied |
| 1170 | // them into the CfgOption after creating the subnet but it had two issues. First, |
| 1171 | // it cost performance. Second, copying options reset the isEncapsulated() flag. |
| 1172 | // If the options have been encapsulated we want to preserve the flag to ensure |
| 1173 | // they are not encapsulated several times. |
| 1174 | ConstElementPtr option_data = pd_pool->get("option-data"); |
| 1175 | if (option_data) { |
| 1176 | auto opts_parser = createOptionDataListParser(); |
| 1177 | opts_parser->parse(pool_->getCfgOption(), option_data, encapsulate_options); |
| 1178 | } |
| 1179 | |
| 1180 | if (user_context_) { |
| 1181 | pool_->setContext(user_context_); |
| 1182 | } |
| 1183 | |
| 1184 | if (client_class_) { |
| 1185 | string cclass = client_class_->stringValue(); |
| 1186 | if (!cclass.empty()) { |
| 1187 | pool_->allowClientClass(cclass); |
| 1188 | } |
| 1189 | } |
| 1190 | |
| 1191 | // Setup client class list. |
| 1192 | BaseNetworkParser::getClientClassesElem(pd_pool, |
| 1193 | std::bind(&Pool::allowClientClass, |
| 1194 | boost::dynamic_pointer_cast<Pool>(pool_), ph::_1)); |
| 1195 | |
| 1196 | // Setup additional class list. |
| 1197 | BaseNetworkParser::getAdditionalClassesElem(pd_pool, |
| 1198 | std::bind(&Pool::addAdditionalClass, |
| 1199 | boost::dynamic_pointer_cast<Pool>(pool_), ph::_1)); |
| 1200 | |
| 1201 | // Add the local pool to the external storage ptr. |
| 1202 | pools->push_back(pool_); |
| 1203 | } |
| 1204 | |
| 1205 | boost::shared_ptr<OptionDataListParser> |
| 1206 | PdPoolParser::createOptionDataListParser() const { |
| 1207 | return (boost::make_shared<OptionDataListParser>(AF_INET610)); |
| 1208 | } |
| 1209 | |
| 1210 | //**************************** PdPoolsListParser ************************ |
| 1211 | |
| 1212 | void |
| 1213 | PdPoolsListParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_list) { |
| 1214 | // Loop through the list of pd pools. |
| 1215 | for (auto const& pd_pool : pd_pool_list->listValue()) { |
| 1216 | auto const& parser = createPdPoolConfigParser(); |
| 1217 | parser->parse(pools, pd_pool); |
| 1218 | } |
| 1219 | } |
| 1220 | |
| 1221 | boost::shared_ptr<PdPoolParser> |
| 1222 | PdPoolsListParser::createPdPoolConfigParser() const { |
| 1223 | return (boost::make_shared<PdPoolParser>()); |
| 1224 | } |
| 1225 | |
| 1226 | //**************************** Subnet6ConfigParser *********************** |
| 1227 | |
| 1228 | Subnet6ConfigParser::Subnet6ConfigParser(bool check_iface) |
| 1229 | : SubnetConfigParser(AF_INET610, check_iface) { |
| 1230 | } |
| 1231 | |
| 1232 | Subnet6Ptr |
| 1233 | Subnet6ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) { |
| 1234 | // Check parameters. |
| 1235 | checkKeywords(SimpleParser6::SUBNET6_PARAMETERS, subnet); |
| 1236 | |
| 1237 | /// Parse all pools first. |
| 1238 | ConstElementPtr pools = subnet->get("pools"); |
| 1239 | if (pools) { |
| 1240 | auto const& parser = createPoolsListParser(); |
| 1241 | parser->parse(pools_, pools, encapsulate_options); |
| 1242 | } |
| 1243 | ConstElementPtr pd_pools = subnet->get("pd-pools"); |
| 1244 | if (pd_pools) { |
| 1245 | auto const& parser = createPdPoolsListParser(); |
| 1246 | parser->parse(pools_, pd_pools); |
| 1247 | } |
| 1248 | |
| 1249 | SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options); |
| 1250 | |
| 1251 | if (!generic) { |
| 1252 | // Sanity check: not supposed to fail. |
| 1253 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Failed to create an IPv6 subnet (" << subnet->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1255, oss__ .str().c_str()); } while (1) |
| 1254 | "Failed to create an IPv6 subnet (" <<do { std::ostringstream oss__; oss__ << "Failed to create an IPv6 subnet (" << subnet->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1255, oss__ .str().c_str()); } while (1) |
| 1255 | subnet->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create an IPv6 subnet (" << subnet->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1255, oss__ .str().c_str()); } while (1); |
| 1256 | } |
| 1257 | |
| 1258 | Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_); |
| 1259 | if (!sn6ptr) { |
| 1260 | // If we hit this, it is a programming error. |
| 1261 | isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "Invalid Subnet6 cast in Subnet6ConfigParser::parse" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1262, oss__.str().c_str()); } while (1) |
| 1262 | "Invalid Subnet6 cast in Subnet6ConfigParser::parse")do { std::ostringstream oss__; oss__ << "Invalid Subnet6 cast in Subnet6ConfigParser::parse" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1262, oss__.str().c_str()); } while (1); |
| 1263 | } |
| 1264 | |
| 1265 | // Set relay information if it was provided |
| 1266 | if (relay_info_) { |
| 1267 | sn6ptr->setRelayInfo(*relay_info_); |
| 1268 | } |
| 1269 | |
| 1270 | // Parse Host Reservations for this subnet if any. |
| 1271 | ConstElementPtr reservations = subnet->get("reservations"); |
| 1272 | if (reservations) { |
| 1273 | HostCollection hosts; |
| 1274 | HostReservationsListParser<HostReservationParser6> parser; |
| 1275 | parser.parse(subnet_->getID(), reservations, hosts); |
| 1276 | for (auto const& h : hosts) { |
| 1277 | validateResvs(sn6ptr, h); |
| 1278 | CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h); |
| 1279 | } |
| 1280 | } |
| 1281 | |
| 1282 | // Parse allocator specification. |
| 1283 | auto network = boost::dynamic_pointer_cast<Network>(sn6ptr); |
| 1284 | parseAllocatorParams(subnet, network); |
| 1285 | |
| 1286 | // Parse pd-allocator specification. |
| 1287 | auto network6 = boost::dynamic_pointer_cast<Network6>(sn6ptr); |
| 1288 | parsePdAllocatorParams(subnet, network6); |
| 1289 | |
| 1290 | // Instantiate the allocators. |
| 1291 | sn6ptr->createAllocators(); |
| 1292 | |
| 1293 | return (sn6ptr); |
| 1294 | } |
| 1295 | |
| 1296 | // Unused? |
| 1297 | void |
| 1298 | Subnet6ConfigParser::duplicateOptionWarning(uint32_t code, |
| 1299 | asiolink::IOAddress& addr) { |
| 1300 | LOG_WARN(dhcpsrv_logger, DHCPSRV_CFGMGR_OPTION_DUPLICATE)if (!(dhcpsrv_logger).isWarnEnabled()) { } else (dhcpsrv_logger ).warn((DHCPSRV_CFGMGR_OPTION_DUPLICATE)) |
| 1301 | .arg(code).arg(addr.toText()); |
| 1302 | } |
| 1303 | |
| 1304 | void |
| 1305 | Subnet6ConfigParser::initSubnet(data::ConstElementPtr params, |
| 1306 | asiolink::IOAddress addr, uint8_t len) { |
| 1307 | // Subnet ID is required and must be in 1..SUBNET_ID_MAX. |
| 1308 | int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX); |
| 1309 | SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1, |
| 1310 | subnet_id_max)); |
| 1311 | |
| 1312 | // We want to log whether rapid-commit is enabled, so we get this |
| 1313 | // before the actual subnet creation. |
| 1314 | Optional<bool> rapid_commit; |
| 1315 | if (params->contains("rapid-commit")) { |
| 1316 | rapid_commit = getBoolean(params, "rapid-commit"); |
| 1317 | } |
| 1318 | |
| 1319 | // Parse preferred lifetime as it is not parsed by the common function. |
| 1320 | Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime"); |
| 1321 | |
| 1322 | // Create a new subnet. |
| 1323 | auto subnet6 = Subnet6::create(addr, len, Triplet<uint32_t>(), |
| 1324 | Triplet<uint32_t>(), |
| 1325 | pref, |
| 1326 | Triplet<uint32_t>(), |
| 1327 | subnet_id); |
| 1328 | subnet_ = subnet6; |
| 1329 | |
| 1330 | ElementPtr mutable_params; |
| 1331 | mutable_params = boost::const_pointer_cast<Element>(params); |
| 1332 | |
| 1333 | // Parse parameters common to all Network derivations. |
| 1334 | NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_); |
| 1335 | parseCommon(mutable_params, network); |
| 1336 | |
| 1337 | // Enable or disable Rapid Commit option support for the subnet. |
| 1338 | if (!rapid_commit.unspecified()) { |
| 1339 | subnet6->setRapidCommit(rapid_commit); |
| 1340 | } |
| 1341 | |
| 1342 | std::ostringstream output; |
| 1343 | output << addr << "/" << static_cast<int>(len) << " with params: "; |
| 1344 | // t1 and t2 are optional may be not specified. |
| 1345 | |
| 1346 | bool has_renew = !subnet6->getT1().unspecified(); |
| 1347 | bool has_rebind = !subnet6->getT2().unspecified(); |
| 1348 | int64_t renew = -1; |
| 1349 | int64_t rebind = -1; |
| 1350 | |
| 1351 | if (has_renew) { |
| 1352 | renew = subnet6->getT1().get(); |
| 1353 | output << "t1=" << renew << ", "; |
| 1354 | } |
| 1355 | if (has_rebind) { |
| 1356 | rebind = subnet6->getT2().get(); |
| 1357 | output << "t2=" << rebind << ", "; |
| 1358 | } |
| 1359 | |
| 1360 | if (!subnet6->getPreferred().unspecified()) { |
| 1361 | output << "preferred-lifetime=" << subnet6->getPreferred().get() << ", "; |
| 1362 | } |
| 1363 | if (!subnet6->getValid().unspecified()) { |
| 1364 | output << "valid-lifetime=" << subnet6->getValid().get(); |
| 1365 | } |
| 1366 | if (!subnet6->getRapidCommit().unspecified()) { |
| 1367 | output << ", rapid-commit is " |
| 1368 | << boolalpha << subnet6->getRapidCommit().get(); |
| 1369 | } |
| 1370 | |
| 1371 | LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_NEW_SUBNET6)if (!(dhcpsrv_logger).isInfoEnabled()) { } else (dhcpsrv_logger ).info((DHCPSRV_CFGMGR_NEW_SUBNET6)).arg(output.str()); |
| 1372 | |
| 1373 | // Get interface-id option content. For now we support string |
| 1374 | // representation only |
| 1375 | Optional<std::string> ifaceid; |
| 1376 | if (params->contains("interface-id")) { |
| 1377 | ifaceid = getString(params, "interface-id"); |
| 1378 | } |
| 1379 | |
| 1380 | Optional<std::string> iface; |
| 1381 | if (params->contains("interface")) { |
| 1382 | iface = getString(params, "interface"); |
| 1383 | } |
| 1384 | |
| 1385 | // Specifying both interface for locally reachable subnets and |
| 1386 | // interface id for relays is mutually exclusive. Need to test for |
| 1387 | // this condition. |
| 1388 | if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() && |
| 1389 | !iface.empty()) { |
| 1390 | isc_throw(isc::dhcp::DhcpConfigError,do { std::ostringstream oss__; oss__ << "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 << "(" << params->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1395, oss__.str().c_str()); } while (1) |
| 1391 | "parser error: interface (defined for locally reachable "do { std::ostringstream oss__; oss__ << "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 << "(" << params->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1395, oss__.str().c_str()); } while (1) |
| 1392 | "subnets) and interface-id (defined for subnets reachable"do { std::ostringstream oss__; oss__ << "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 << "(" << params->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1395, oss__.str().c_str()); } while (1) |
| 1393 | " via relays) cannot be defined at the same time for "do { std::ostringstream oss__; oss__ << "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 << "(" << params->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1395, oss__.str().c_str()); } while (1) |
| 1394 | "subnet " << addr << "/" << (int)len << "("do { std::ostringstream oss__; oss__ << "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 << "(" << params->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1395, oss__.str().c_str()); } while (1) |
| 1395 | << params->getPosition() << ")")do { std::ostringstream oss__; oss__ << "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 << "(" << params->getPosition() << ")"; throw isc ::dhcp::DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1395, oss__.str().c_str()); } while (1); |
| 1396 | } |
| 1397 | |
| 1398 | // Configure interface-id for remote interfaces, if defined |
| 1399 | if (!ifaceid.unspecified() && !ifaceid.empty()) { |
| 1400 | std::string ifaceid_value = ifaceid.get(); |
| 1401 | OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end()); |
| 1402 | OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); |
| 1403 | subnet6->setInterfaceId(opt); |
| 1404 | } |
| 1405 | |
| 1406 | // Get interface name. If it is defined, then the subnet is available |
| 1407 | // directly over specified network interface. |
| 1408 | if (!iface.unspecified() && !iface.empty()) { |
| 1409 | if (check_iface_ && !IfaceMgr::instance().getIface(iface)) { |
| 1410 | ConstElementPtr error = params->get("interface"); |
| 1411 | isc_throw(DhcpConfigError, "Specified network interface name " << ifacedo { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet6-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1414, oss__.str().c_str()); } while (1) |
| 1412 | << " for subnet " << subnet6->toText()do { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet6-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1414, oss__.str().c_str()); } while (1) |
| 1413 | << " is not present in the system ("do { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet6-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1414, oss__.str().c_str()); } while (1) |
| 1414 | << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Specified network interface name " << iface << " for subnet " << subnet6-> toText() << " is not present in the system (" << error ->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1414, oss__.str().c_str()); } while (1); |
| 1415 | } |
| 1416 | |
| 1417 | subnet6->setIface(iface); |
| 1418 | } |
| 1419 | |
| 1420 | // Try setting up client class. |
| 1421 | if (params->contains("client-class")) { |
| 1422 | string client_class = getString(params, "client-class"); |
| 1423 | if (!client_class.empty()) { |
| 1424 | subnet6->allowClientClass(client_class); |
| 1425 | } |
| 1426 | } |
| 1427 | |
| 1428 | // Setup client class list. |
| 1429 | getClientClassesElem(params, std::bind(&Network::allowClientClass, |
| 1430 | boost::dynamic_pointer_cast<Network>(subnet6), ph::_1)); |
| 1431 | |
| 1432 | // Setup additional class list. |
| 1433 | getAdditionalClassesElem(params, std::bind(&Network::addAdditionalClass, |
| 1434 | boost::dynamic_pointer_cast<Network>(subnet6), ph::_1)); |
| 1435 | |
| 1436 | /// client-class processing is now generic and handled in the common |
| 1437 | /// code (see isc::data::SubnetConfigParser::createSubnet) |
| 1438 | |
| 1439 | // Parse t1-percent and t2-percent |
| 1440 | parseTeePercents(params, network); |
| 1441 | |
| 1442 | // Parse DDNS parameters |
| 1443 | parseDdnsParams(params, network); |
| 1444 | |
| 1445 | // Parse lease cache parameters |
| 1446 | parseCacheParams(params, network); |
| 1447 | |
| 1448 | // Parse adaptive lease time parameter. |
| 1449 | parseAdaptiveLeaseTimeParam(params, network); |
| 1450 | } |
| 1451 | |
| 1452 | void |
| 1453 | Subnet6ConfigParser::validateResvs(const Subnet6Ptr& subnet, ConstHostPtr host) { |
| 1454 | const IPv6ResrvRange& range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA); |
| 1455 | BOOST_FOREACH(auto const& it, range)if (boost::foreach_detail_::auto_any_t _foreach_col1455 = boost ::foreach_detail_::contain( (range) , (true ? nullptr : boost ::foreach_detail_::or_( boost::foreach_detail_::is_rvalue_((range ), 0) , boost::foreach_detail_::and_( boost::foreach_detail_:: not_(boost_foreach_is_noncopyable( boost::foreach_detail_::to_ptr (range) , boost_foreach_argument_dependent_lookup_hack_value) ) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_ ::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value )))))) {} else if (boost::foreach_detail_::auto_any_t _foreach_cur1455 = boost::foreach_detail_::begin( _foreach_col1455 , (true ? nullptr : boost::foreach_detail_::encode_type(range, boost::foreach_detail_ ::is_const_(range))) , (true ? nullptr : boost::foreach_detail_ ::or_( boost::foreach_detail_::is_rvalue_((range), 0) , boost ::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable ( boost::foreach_detail_::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value )) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_ ::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value )))))) {} else if (boost::foreach_detail_::auto_any_t _foreach_end1455 = boost::foreach_detail_::end( _foreach_col1455 , (true ? nullptr : boost::foreach_detail_::encode_type(range, boost::foreach_detail_ ::is_const_(range))) , (true ? nullptr : boost::foreach_detail_ ::or_( boost::foreach_detail_::is_rvalue_((range), 0) , boost ::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable ( boost::foreach_detail_::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value )) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_ ::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value )))))) {} else for (bool _foreach_continue1455 = true; _foreach_continue1455 && !boost::foreach_detail_::done( _foreach_cur1455 , _foreach_end1455 , (true ? nullptr : boost::foreach_detail_:: encode_type(range, boost::foreach_detail_::is_const_(range))) ); _foreach_continue1455 ? boost::foreach_detail_::next( _foreach_cur1455 , (true ? nullptr : boost::foreach_detail_::encode_type(range , boost::foreach_detail_::is_const_(range)))) : (void)0) if ( boost::foreach_detail_::set_false(_foreach_continue1455)) {} else for (auto const& it = boost::foreach_detail_::deref( _foreach_cur1455 , (true ? nullptr : boost::foreach_detail_::encode_type(range , boost::foreach_detail_::is_const_(range)))); !_foreach_continue1455 ; _foreach_continue1455 = true) { |
| 1456 | const IOAddress& address = it.second.getPrefix(); |
| 1457 | if (!subnet->inRange(address)) { |
| 1458 | isc_throw(DhcpConfigError, "specified reservation '" << addressdo { std::ostringstream oss__; oss__ << "specified reservation '" << address << "' is not within the IPv6 subnet '" << subnet->toText() << "'"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1460, oss__ .str().c_str()); } while (1) |
| 1459 | << "' is not within the IPv6 subnet '"do { std::ostringstream oss__; oss__ << "specified reservation '" << address << "' is not within the IPv6 subnet '" << subnet->toText() << "'"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1460, oss__ .str().c_str()); } while (1) |
| 1460 | << subnet->toText() << "'")do { std::ostringstream oss__; oss__ << "specified reservation '" << address << "' is not within the IPv6 subnet '" << subnet->toText() << "'"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1460, oss__ .str().c_str()); } while (1); |
| 1461 | } |
| 1462 | } |
| 1463 | } |
| 1464 | |
| 1465 | boost::shared_ptr<PoolsListParser> |
| 1466 | Subnet6ConfigParser::createPoolsListParser() const { |
| 1467 | return (boost::make_shared<Pools6ListParser>()); |
| 1468 | } |
| 1469 | |
| 1470 | boost::shared_ptr<PdPoolsListParser> |
| 1471 | Subnet6ConfigParser::createPdPoolsListParser() const { |
| 1472 | return (boost::make_shared<PdPoolsListParser>()); |
| 1473 | } |
| 1474 | |
| 1475 | //**************************** Subnet6ListConfigParser ******************** |
| 1476 | |
| 1477 | Subnets6ListConfigParser::Subnets6ListConfigParser(bool check_iface) |
| 1478 | : check_iface_(check_iface) { |
| 1479 | } |
| 1480 | |
| 1481 | size_t |
| 1482 | Subnets6ListConfigParser::parse(SrvConfigPtr cfg, |
| 1483 | ConstElementPtr subnets_list, |
| 1484 | bool encapsulate_options) { |
| 1485 | size_t cnt = 0; |
| 1486 | for (auto const& subnet_json : subnets_list->listValue()) { |
| 1487 | |
| 1488 | auto const& parser = createSubnetConfigParser(); |
| 1489 | Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options); |
| 1490 | |
| 1491 | // Adding a subnet to the Configuration Manager may fail if the |
| 1492 | // subnet id is invalid (duplicate). Thus, we catch exceptions |
| 1493 | // here to append a position in the configuration string. |
| 1494 | try { |
| 1495 | cfg->getCfgSubnets6()->add(subnet); |
| 1496 | cnt++; |
| 1497 | } catch (const std::exception& ex) { |
| 1498 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1499, oss__.str().c_str()); } while (1) |
| 1499 | << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1499, oss__.str().c_str()); } while (1); |
| 1500 | } |
| 1501 | } |
| 1502 | return (cnt); |
| 1503 | } |
| 1504 | |
| 1505 | size_t |
| 1506 | Subnets6ListConfigParser::parse(Subnet6Collection& subnets, |
| 1507 | ConstElementPtr subnets_list, |
| 1508 | bool encapsulate_options) { |
| 1509 | size_t cnt = 0; |
| 1510 | for (auto const& subnet_json : subnets_list->listValue()) { |
| 1511 | |
| 1512 | auto const& parser = createSubnetConfigParser(); |
| 1513 | Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options); |
| 1514 | if (subnet) { |
| 1515 | try { |
| 1516 | auto ret = subnets.insert(subnet); |
| 1517 | if (!ret.second) { |
| 1518 | isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1519, oss__.str().c_str()); } while (1) |
| 1519 | "can't store subnet because of conflict")do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict" ; throw Unexpected("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1519, oss__.str().c_str()); } while (1); |
| 1520 | } |
| 1521 | ++cnt; |
| 1522 | } catch (const std::exception& ex) { |
| 1523 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1524, oss__.str().c_str()); } while (1) |
| 1524 | << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << subnet_json->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1524, oss__.str().c_str()); } while (1); |
| 1525 | } |
| 1526 | } |
| 1527 | } |
| 1528 | return (cnt); |
| 1529 | } |
| 1530 | |
| 1531 | boost::shared_ptr<Subnet6ConfigParser> |
| 1532 | Subnets6ListConfigParser::createSubnetConfigParser() const { |
| 1533 | return (boost::make_shared<Subnet6ConfigParser>(check_iface_)); |
| 1534 | } |
| 1535 | |
| 1536 | //**************************** D2ClientConfigParser ********************** |
| 1537 | |
| 1538 | dhcp_ddns::NameChangeProtocol |
| 1539 | D2ClientConfigParser::getProtocol(ConstElementPtr scope, |
| 1540 | const std::string& name) { |
| 1541 | return (getAndConvert<dhcp_ddns::NameChangeProtocol, |
| 1542 | dhcp_ddns::stringToNcrProtocol> |
| 1543 | (scope, name, "NameChangeRequest protocol")); |
| 1544 | } |
| 1545 | |
| 1546 | dhcp_ddns::NameChangeFormat |
| 1547 | D2ClientConfigParser::getFormat(ConstElementPtr scope, |
| 1548 | const std::string& name) { |
| 1549 | return (getAndConvert<dhcp_ddns::NameChangeFormat, |
| 1550 | dhcp_ddns::stringToNcrFormat> |
| 1551 | (scope, name, "NameChangeRequest format")); |
| 1552 | } |
| 1553 | |
| 1554 | D2ClientConfig::ReplaceClientNameMode |
| 1555 | D2ClientConfigParser::getMode(ConstElementPtr scope, |
| 1556 | const std::string& name) { |
| 1557 | return (getAndConvert<D2ClientConfig::ReplaceClientNameMode, |
| 1558 | D2ClientConfig::stringToReplaceClientNameMode> |
| 1559 | (scope, name, "ReplaceClientName mode")); |
| 1560 | } |
| 1561 | |
| 1562 | D2ClientConfigPtr |
| 1563 | D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) { |
| 1564 | D2ClientConfigPtr new_config; |
| 1565 | |
| 1566 | // Get all parameters that are needed to create the D2ClientConfig. |
| 1567 | bool enable_updates = getBoolean(client_config, "enable-updates"); |
| 1568 | |
| 1569 | IOAddress server_ip = getAddress(client_config, "server-ip"); |
| 1570 | |
| 1571 | uint32_t server_port = getUint32(client_config, "server-port"); |
| 1572 | |
| 1573 | std::string sender_ip_str = getString(client_config, "sender-ip"); |
| 1574 | |
| 1575 | uint32_t sender_port = getUint32(client_config, "sender-port"); |
| 1576 | |
| 1577 | uint32_t max_queue_size = getUint32(client_config, "max-queue-size"); |
| 1578 | |
| 1579 | dhcp_ddns::NameChangeProtocol ncr_protocol = |
| 1580 | getProtocol(client_config, "ncr-protocol"); |
| 1581 | |
| 1582 | dhcp_ddns::NameChangeFormat ncr_format = |
| 1583 | getFormat(client_config, "ncr-format"); |
| 1584 | |
| 1585 | IOAddress sender_ip(0); |
| 1586 | if (sender_ip_str.empty()) { |
| 1587 | // The default sender IP depends on the server IP family |
| 1588 | sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() : |
| 1589 | IOAddress::IPV6_ZERO_ADDRESS()); |
| 1590 | } else { |
| 1591 | try { |
| 1592 | sender_ip = IOAddress(sender_ip_str); |
| 1593 | } catch (const std::exception& ex) { |
| 1594 | isc_throw(DhcpConfigError, "invalid address (" << sender_ip_strdo { std::ostringstream oss__; oss__ << "invalid address (" << sender_ip_str << ") specified for parameter 'sender-ip' (" << getPosition("sender-ip", client_config) << ")" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1596, oss__.str().c_str()); } while (1) |
| 1595 | << ") specified for parameter 'sender-ip' ("do { std::ostringstream oss__; oss__ << "invalid address (" << sender_ip_str << ") specified for parameter 'sender-ip' (" << getPosition("sender-ip", client_config) << ")" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1596, oss__.str().c_str()); } while (1) |
| 1596 | << getPosition("sender-ip", client_config) << ")")do { std::ostringstream oss__; oss__ << "invalid address (" << sender_ip_str << ") specified for parameter 'sender-ip' (" << getPosition("sender-ip", client_config) << ")" ; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1596, oss__.str().c_str()); } while (1); |
| 1597 | } |
| 1598 | } |
| 1599 | |
| 1600 | // Now we check for logical errors. This repeats what is done in |
| 1601 | // D2ClientConfig::validate(), but doing it here permits us to |
| 1602 | // emit meaningful parameter position info in the error. |
| 1603 | if (ncr_format != dhcp_ddns::FMT_JSON) { |
| 1604 | isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: " << dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. (" << getPosition("ncr-format", client_config) << ")" ; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1607, oss__.str().c_str()); } while (1) |
| 1605 | << dhcp_ddns::ncrFormatToString(ncr_format)do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: " << dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. (" << getPosition("ncr-format", client_config) << ")" ; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1607, oss__.str().c_str()); } while (1) |
| 1606 | << " is not supported. ("do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: " << dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. (" << getPosition("ncr-format", client_config) << ")" ; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1607, oss__.str().c_str()); } while (1) |
| 1607 | << getPosition("ncr-format", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: " << dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. (" << getPosition("ncr-format", client_config) << ")" ; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1607, oss__.str().c_str()); } while (1); |
| 1608 | } |
| 1609 | |
| 1610 | if (ncr_protocol != dhcp_ddns::NCR_UDP) { |
| 1611 | isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: " << dhcp_ddns::ncrProtocolToString(ncr_protocol) << " is not supported. (" << getPosition("ncr-protocol", client_config ) << ")"; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1614, oss__.str().c_str()); } while (1) |
| 1612 | << dhcp_ddns::ncrProtocolToString(ncr_protocol)do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: " << dhcp_ddns::ncrProtocolToString(ncr_protocol) << " is not supported. (" << getPosition("ncr-protocol", client_config ) << ")"; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1614, oss__.str().c_str()); } while (1) |
| 1613 | << " is not supported. ("do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: " << dhcp_ddns::ncrProtocolToString(ncr_protocol) << " is not supported. (" << getPosition("ncr-protocol", client_config ) << ")"; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1614, oss__.str().c_str()); } while (1) |
| 1614 | << getPosition("ncr-protocol", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: " << dhcp_ddns::ncrProtocolToString(ncr_protocol) << " is not supported. (" << getPosition("ncr-protocol", client_config ) << ")"; throw D2ClientError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1614, oss__.str().c_str()); } while (1); |
| 1615 | } |
| 1616 | |
| 1617 | if (sender_ip.getFamily() != server_ip.getFamily()) { |
| 1618 | isc_throw(D2ClientError,do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1) |
| 1619 | "D2ClientConfig error: address family mismatch: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1) |
| 1620 | << "server-ip: " << server_ip.toText()do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1) |
| 1621 | << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1) |
| 1622 | << " while sender-ip: " << sender_ip.toText()do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1) |
| 1623 | << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1) |
| 1624 | << " (" << getPosition("sender-ip", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: " << "server-ip: " << server_ip.toText() << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: " << sender_ip.toText() << " is: " << (sender_ip .isV4() ? "IPv4" : "IPv6") << " (" << getPosition ("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1624, oss__ .str().c_str()); } while (1); |
| 1625 | } |
| 1626 | |
| 1627 | if (server_ip == sender_ip && server_port == sender_port) { |
| 1628 | isc_throw(D2ClientError,do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot" " share the exact same IP address/port: " << server_ip .toText() << "/" << server_port << " (" << getPosition("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1632, oss__ .str().c_str()); } while (1) |
| 1629 | "D2ClientConfig error: server and sender cannot"do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot" " share the exact same IP address/port: " << server_ip .toText() << "/" << server_port << " (" << getPosition("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1632, oss__ .str().c_str()); } while (1) |
| 1630 | " share the exact same IP address/port: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot" " share the exact same IP address/port: " << server_ip .toText() << "/" << server_port << " (" << getPosition("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1632, oss__ .str().c_str()); } while (1) |
| 1631 | << server_ip.toText() << "/" << server_portdo { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot" " share the exact same IP address/port: " << server_ip .toText() << "/" << server_port << " (" << getPosition("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1632, oss__ .str().c_str()); } while (1) |
| 1632 | << " (" << getPosition("sender-ip", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot" " share the exact same IP address/port: " << server_ip .toText() << "/" << server_port << " (" << getPosition("sender-ip", client_config) << ")"; throw D2ClientError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1632, oss__ .str().c_str()); } while (1); |
| 1633 | } |
| 1634 | |
| 1635 | try { |
| 1636 | // Attempt to create the new client config. |
| 1637 | new_config.reset(new D2ClientConfig(enable_updates, |
| 1638 | server_ip, |
| 1639 | server_port, |
| 1640 | sender_ip, |
| 1641 | sender_port, |
| 1642 | max_queue_size, |
| 1643 | ncr_protocol, |
| 1644 | ncr_format)); |
| 1645 | } catch (const std::exception& ex) { |
| 1646 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << client_config->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1647, oss__.str().c_str()); } while (1) |
| 1647 | << client_config->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << client_config->getPosition() << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1647, oss__.str().c_str()); } while (1); |
| 1648 | } |
| 1649 | |
| 1650 | // Add user context |
| 1651 | ConstElementPtr user_context = client_config->get("user-context"); |
| 1652 | if (user_context) { |
| 1653 | new_config->setContext(user_context); |
| 1654 | } |
| 1655 | |
| 1656 | return (new_config); |
| 1657 | } |
| 1658 | |
| 1659 | /// @brief This table defines default values for D2 client configuration |
| 1660 | const SimpleDefaults D2ClientConfigParser::D2_CLIENT_CONFIG_DEFAULTS = { |
| 1661 | // enable-updates is unconditionally required |
| 1662 | { "server-ip", Element::string, "127.0.0.1" }, |
| 1663 | { "server-port", Element::integer, "53001" }, |
| 1664 | // default sender-ip depends on server-ip family, so we leave default blank |
| 1665 | // parser knows to use the appropriate ZERO address based on server-ip |
| 1666 | { "sender-ip", Element::string, "" }, |
| 1667 | { "sender-port", Element::integer, "0" }, |
| 1668 | { "max-queue-size", Element::integer, "1024" }, |
| 1669 | { "ncr-protocol", Element::string, "UDP" }, |
| 1670 | { "ncr-format", Element::string, "JSON" } |
| 1671 | }; |
| 1672 | |
| 1673 | size_t |
| 1674 | D2ClientConfigParser::setAllDefaults(isc::data::ConstElementPtr d2_config) { |
| 1675 | ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config); |
| 1676 | return (SimpleParser::setDefaults(mutable_d2, D2_CLIENT_CONFIG_DEFAULTS)); |
| 1677 | } |
| 1678 | |
| 1679 | void |
| 1680 | CompatibilityParser::parse(ConstElementPtr compatibility, SrvConfig& srv_cfg) { |
| 1681 | if (compatibility) { |
| 1682 | auto family = CfgMgr::instance().getFamily(); |
| 1683 | for (auto const& kv : compatibility->mapValue()) { |
| 1684 | if (!kv.second || (kv.second->getType() != Element::boolean)) { |
| 1685 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "compatibility parameter values must be " << "boolean (" << kv.first << " at " << kv.second->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1688, oss__ .str().c_str()); } while (1) |
| 1686 | "compatibility parameter values must be "do { std::ostringstream oss__; oss__ << "compatibility parameter values must be " << "boolean (" << kv.first << " at " << kv.second->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1688, oss__ .str().c_str()); } while (1) |
| 1687 | << "boolean (" << kv.first << " at "do { std::ostringstream oss__; oss__ << "compatibility parameter values must be " << "boolean (" << kv.first << " at " << kv.second->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1688, oss__ .str().c_str()); } while (1) |
| 1688 | << kv.second->getPosition() << ")")do { std::ostringstream oss__; oss__ << "compatibility parameter values must be " << "boolean (" << kv.first << " at " << kv.second->getPosition() << ")"; throw DhcpConfigError ("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc", 1688, oss__ .str().c_str()); } while (1); |
| 1689 | } |
| 1690 | if (kv.first == "lenient-option-parsing") { |
| 1691 | srv_cfg.setLenientOptionParsing(kv.second->boolValue()); |
| 1692 | } else if (family == AF_INET2) { |
| 1693 | if (kv.first == "ignore-dhcp-server-identifier") { |
| 1694 | srv_cfg.setIgnoreServerIdentifier(kv.second->boolValue()); |
| 1695 | } else if (kv.first == "ignore-rai-link-selection") { |
| 1696 | srv_cfg.setIgnoreRAILinkSelection(kv.second->boolValue()); |
| 1697 | } else if (kv.first == "exclude-first-last-24") { |
| 1698 | srv_cfg.setExcludeFirstLast24(kv.second->boolValue()); |
| 1699 | } else { |
| 1700 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1703, oss__.str().c_str()); } while (1) |
| 1701 | "unsupported compatibility parameter: "do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1703, oss__.str().c_str()); } while (1) |
| 1702 | << kv.first << " (" << kv.second->getPosition()do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1703, oss__.str().c_str()); } while (1) |
| 1703 | << ")")do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1703, oss__.str().c_str()); } while (1); |
| 1704 | } |
| 1705 | } else { |
| 1706 | isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1709, oss__.str().c_str()); } while (1) |
| 1707 | "unsupported compatibility parameter: "do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1709, oss__.str().c_str()); } while (1) |
| 1708 | << kv.first << " (" << kv.second->getPosition()do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1709, oss__.str().c_str()); } while (1) |
| 1709 | << ")")do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: " << kv.first << " (" << kv.second->getPosition () << ")"; throw DhcpConfigError("../../../src/lib/dhcpsrv/parsers/dhcp_parsers.cc" , 1709, oss__.str().c_str()); } while (1); |
| 1710 | } |
| 1711 | } |
| 1712 | } |
| 1713 | } |
| 1714 | |
| 1715 | } // namespace dhcp |
| 1716 | } // namespace isc |