123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- #include <config/ccsession.h>
- #include <dhcp4/dhcp4_log.h>
- #include <dhcp/libdhcp++.h>
- #include <dhcp/option_definition.h>
- #include <dhcpsrv/cfgmgr.h>
- #include <dhcp4/json_config_parser.h>
- #include <dhcpsrv/dbaccess_parser.h>
- #include <dhcpsrv/dhcp_parsers.h>
- #include <dhcpsrv/option_space_container.h>
- #include <util/encode/hex.h>
- #include <util/strutil.h>
- #include <boost/foreach.hpp>
- #include <boost/lexical_cast.hpp>
- #include <boost/algorithm/string.hpp>
- #include <limits>
- #include <iostream>
- #include <vector>
- #include <map>
- using namespace std;
- using namespace isc;
- using namespace isc::dhcp;
- using namespace isc::data;
- using namespace isc::asiolink;
- namespace {
- class Dhcp4OptionDataParser : public OptionDataParser {
- public:
-
-
-
-
-
-
-
- Dhcp4OptionDataParser(const std::string&,
- OptionStoragePtr options, ParserContextPtr global_context)
- :OptionDataParser("", options, global_context) {
- }
-
-
-
-
-
-
-
-
- static OptionDataParser* factory(const std::string& param_name,
- OptionStoragePtr options, ParserContextPtr global_context) {
- return (new Dhcp4OptionDataParser(param_name, options, global_context));
- }
- protected:
-
-
-
-
-
-
-
-
-
-
-
- virtual OptionDefinitionPtr findServerSpaceOptionDefinition (
- std::string& option_space, uint32_t option_code) {
- OptionDefinitionPtr def;
- if (option_space == "dhcp4" &&
- LibDHCP::isStandardOption(Option::V4, option_code)) {
- def = LibDHCP::getOptionDef(Option::V4, option_code);
- } else if (option_space == "dhcp6") {
- isc_throw(DhcpConfigError, "'dhcp6' option space name is reserved"
- << " for DHCPv6 server");
- } else {
-
-
- uint32_t vendor_id = SubnetConfigParser::optionSpaceToVendorId(option_space);
- if (vendor_id) {
- def = LibDHCP::getVendorOptionDef(Option::V4, vendor_id, option_code);
- }
- }
- return (def);
- }
- };
- class Pool4Parser : public PoolParser {
- public:
-
-
-
-
-
-
- Pool4Parser(const std::string& param_name, PoolStoragePtr pools)
- :PoolParser(param_name, pools) {
- }
- protected:
-
-
-
-
-
-
-
- PoolPtr poolMaker (IOAddress &addr, uint32_t len, int32_t) {
- return (PoolPtr(new Pool4(addr, len)));
- }
-
-
-
-
-
-
-
- PoolPtr poolMaker (IOAddress &min, IOAddress &max, int32_t) {
- return (PoolPtr(new Pool4(min, max)));
- }
- };
- class Pools4ListParser : public PoolsListParser {
- public:
- Pools4ListParser(const std::string& dummy, PoolStoragePtr pools)
- :PoolsListParser(dummy, pools) {
- }
- protected:
- virtual ParserPtr poolParserMaker(PoolStoragePtr storage) {
- return (ParserPtr(new Pool4Parser("pool", storage)));
- }
- };
- class Subnet4ConfigParser : public SubnetConfigParser {
- public:
-
-
-
-
- Subnet4ConfigParser(const std::string&)
- :SubnetConfigParser("", globalContext(), IOAddress("0.0.0.0")) {
- }
-
-
-
-
- void build(ConstElementPtr subnet) {
- SubnetConfigParser::build(subnet);
- if (subnet_) {
- Subnet4Ptr sub4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
- if (!sub4ptr) {
-
- isc_throw(Unexpected,
- "Invalid cast in Subnet4ConfigParser::commit");
- }
-
- if (relay_info_) {
- sub4ptr->setRelayInfo(*relay_info_);
- }
-
-
-
- try {
- isc::dhcp::CfgMgr::instance().addSubnet4(sub4ptr);
- } catch (const std::exception& ex) {
- isc_throw(DhcpConfigError, ex.what() << " ("
- << subnet->getPosition() << ")");
- }
- }
- }
-
-
-
-
- void commit() { }
- protected:
-
-
-
-
-
-
-
-
- DhcpConfigParser* createSubnetConfigParser(const std::string& config_id) {
- DhcpConfigParser* parser = NULL;
- if ((config_id.compare("valid-lifetime") == 0) ||
- (config_id.compare("renew-timer") == 0) ||
- (config_id.compare("rebind-timer") == 0) ||
- (config_id.compare("id") == 0)) {
- parser = new Uint32Parser(config_id, uint32_values_);
- } else if ((config_id.compare("subnet") == 0) ||
- (config_id.compare("interface") == 0) ||
- (config_id.compare("client-class") == 0) ||
- (config_id.compare("next-server") == 0)) {
- parser = new StringParser(config_id, string_values_);
- } else if (config_id.compare("pools") == 0) {
- parser = new Pools4ListParser(config_id, pools_);
- } else if (config_id.compare("relay") == 0) {
- parser = new RelayInfoParser(config_id, relay_info_, Option::V4);
- } else if (config_id.compare("option-data") == 0) {
- parser = new OptionDataListParser(config_id, options_,
- global_context_,
- Dhcp4OptionDataParser::factory);
- } else {
- isc_throw(NotImplemented, "unsupported parameter: " << config_id);
- }
- return (parser);
- }
-
-
-
-
-
-
-
- bool isServerStdOption(std::string option_space, uint32_t code) {
- return ((option_space.compare("dhcp4") == 0)
- && LibDHCP::isStandardOption(Option::V4, code));
- }
-
-
-
-
- OptionDefinitionPtr getServerStdOptionDefinition (uint32_t code) {
- return (LibDHCP::getOptionDef(Option::V4, code));
- }
-
-
-
-
-
-
-
- virtual void duplicate_option_warning(uint32_t code,
- isc::asiolink::IOAddress& addr) {
- LOG_WARN(dhcp4_logger, DHCP4_CONFIG_OPTION_DUPLICATE)
- .arg(code).arg(addr.toText());
- }
-
-
-
-
-
- void initSubnet(isc::asiolink::IOAddress addr, uint8_t len) {
-
-
-
- Triplet<uint32_t> t1 = getOptionalParam("renew-timer");
- Triplet<uint32_t> t2 = getOptionalParam("rebind-timer");
-
-
-
- Triplet<uint32_t> valid = getParam("valid-lifetime");
-
-
- SubnetID subnet_id =
- static_cast<SubnetID>(uint32_values_->getOptionalParam("id", 0));
- stringstream s;
- s << addr << "/" << static_cast<int>(len) << " with params: ";
-
- if (!t1.unspecified()) {
- s << "t1=" << t1 << ", ";
- }
- if (!t2.unspecified()) {
- s << "t2=" << t2 << ", ";
- }
- s <<"valid-lifetime=" << valid;
- LOG_INFO(dhcp4_logger, DHCP4_CONFIG_NEW_SUBNET).arg(s.str());
- Subnet4Ptr subnet4(new Subnet4(addr, len, t1, t2, valid, subnet_id));
- subnet_ = subnet4;
-
- try {
- string next_server = globalContext()->string_values_->getParam("next-server");
- if (!next_server.empty()) {
- subnet4->setSiaddr(IOAddress(next_server));
- }
- } catch (const DhcpConfigError&) {
-
- } catch (...) {
- isc_throw(DhcpConfigError, "invalid parameter next-server ("
- << globalContext()->string_values_->getPosition("next-server")
- << ")");
- }
-
- try {
- string next_server = string_values_->getParam("next-server");
- if (!next_server.empty()) {
- subnet4->setSiaddr(IOAddress(next_server));
- }
- } catch (const DhcpConfigError&) {
-
- } catch (...) {
- isc_throw(DhcpConfigError, "invalid parameter next-server ("
- << string_values_->getPosition("next-server")
- << ")");
- }
-
- try {
- string client_class = string_values_->getParam("client-class");
- subnet4->allowClientClass(client_class);
- } catch (const DhcpConfigError&) {
-
- }
- }
- };
- class Subnets4ListConfigParser : public DhcpConfigParser {
- public:
-
-
-
-
- Subnets4ListConfigParser(const std::string&) {
- }
-
-
-
-
-
-
- void build(ConstElementPtr subnets_list) {
-
-
-
- CfgMgr::instance().deleteSubnets4();
- BOOST_FOREACH(ConstElementPtr subnet, subnets_list->listValue()) {
- ParserPtr parser(new Subnet4ConfigParser("subnet"));
- parser->build(subnet);
- subnets_.push_back(parser);
- }
- }
-
-
-
-
- void commit() {
- BOOST_FOREACH(ParserPtr subnet, subnets_) {
- subnet->commit();
- }
- }
-
-
-
- static DhcpConfigParser* factory(const std::string& param_name) {
- return (new Subnets4ListConfigParser(param_name));
- }
-
- ParserCollection subnets_;
- };
- }
- namespace isc {
- namespace dhcp {
- DhcpConfigParser* createGlobalDhcp4ConfigParser(const std::string& config_id,
- ConstElementPtr element) {
- DhcpConfigParser* parser = NULL;
- if ((config_id.compare("valid-lifetime") == 0) ||
- (config_id.compare("renew-timer") == 0) ||
- (config_id.compare("rebind-timer") == 0)) {
- parser = new Uint32Parser(config_id,
- globalContext()->uint32_values_);
- } else if (config_id.compare("interfaces") == 0) {
- parser = new InterfaceListConfigParser(config_id);
- } else if (config_id.compare("subnet4") == 0) {
- parser = new Subnets4ListConfigParser(config_id);
- } else if (config_id.compare("option-data") == 0) {
- parser = new OptionDataListParser(config_id,
- globalContext()->options_,
- globalContext(),
- Dhcp4OptionDataParser::factory);
- } else if (config_id.compare("option-def") == 0) {
- parser = new OptionDefListParser(config_id, globalContext());
- } else if ((config_id.compare("version") == 0) ||
- (config_id.compare("next-server") == 0)) {
- parser = new StringParser(config_id,
- globalContext()->string_values_);
- } else if (config_id.compare("lease-database") == 0) {
- parser = new DbAccessParser(config_id, *globalContext());
- } else if (config_id.compare("hooks-libraries") == 0) {
- parser = new HooksLibrariesParser(config_id);
- } else if (config_id.compare("echo-client-id") == 0) {
- parser = new BooleanParser(config_id, globalContext()->boolean_values_);
- } else if (config_id.compare("dhcp-ddns") == 0) {
- parser = new D2ClientConfigParser(config_id);
- } else {
- isc_throw(DhcpConfigError,
- "unsupported global configuration parameter: "
- << config_id << " (" << element->getPosition() << ")");
- }
- return (parser);
- }
- void commitGlobalOptions() {
-
-
-
-
- try {
- bool echo_client_id = globalContext()->boolean_values_->getParam("echo-client-id");
- CfgMgr::instance().echoClientId(echo_client_id);
- } catch (...) {
-
- }
- }
- isc::data::ConstElementPtr
- configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
- if (!config_set) {
- ConstElementPtr answer = isc::config::createAnswer(1,
- string("Can't parse NULL config"));
- return (answer);
- }
- LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND,
- DHCP4_CONFIG_START).arg(config_set->str());
-
-
- Subnet::resetSubnetID();
-
-
-
-
-
-
-
- ParserCollection independent_parsers;
- ParserPtr subnet_parser;
- ParserPtr option_parser;
- ParserPtr iface_parser;
-
-
-
- ParserPtr hooks_parser;
-
-
-
-
-
-
-
- ParserContext original_context(*globalContext());
-
- ConstElementPtr answer;
-
-
- bool rollback = false;
-
-
-
- ConfigPair config_pair;
- try {
-
- const std::map<std::string, ConstElementPtr>& values_map =
- config_set->mapValue();
- BOOST_FOREACH(config_pair, values_map) {
- ParserPtr parser(createGlobalDhcp4ConfigParser(config_pair.first,
- config_pair.second));
- LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PARSER_CREATED)
- .arg(config_pair.first);
- if (config_pair.first == "subnet4") {
- subnet_parser = parser;
- } else if (config_pair.first == "option-data") {
- option_parser = parser;
- } else if (config_pair.first == "interfaces") {
-
-
- iface_parser = parser;
- parser->build(config_pair.second);
- } else if (config_pair.first == "hooks-libraries") {
-
-
-
- hooks_parser = parser;
- parser->build(config_pair.second);
- } else {
-
-
- independent_parsers.push_back(parser);
- parser->build(config_pair.second);
-
-
-
- parser->commit();
- }
- }
-
- std::map<std::string, ConstElementPtr>::const_iterator option_config =
- values_map.find("option-data");
- if (option_config != values_map.end()) {
- config_pair.first = "option-data";
- option_parser->build(option_config->second);
- option_parser->commit();
- }
-
- std::map<std::string, ConstElementPtr>::const_iterator subnet_config =
- values_map.find("subnet4");
- if (subnet_config != values_map.end()) {
- config_pair.first = "subnet4";
- subnet_parser->build(subnet_config->second);
- }
- } catch (const isc::Exception& ex) {
- LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
- .arg(config_pair.first).arg(ex.what());
- answer = isc::config::createAnswer(1,
- string("Configuration parsing failed: ") + ex.what());
-
- rollback = true;
- } catch (...) {
-
- LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(config_pair.first);
- answer = isc::config::createAnswer(1,
- string("Configuration parsing failed"));
-
- rollback = true;
- }
-
-
-
-
- if (!rollback) {
- try {
- if (subnet_parser) {
- subnet_parser->commit();
- }
- if (iface_parser) {
- iface_parser->commit();
- }
-
- commitGlobalOptions();
-
-
-
- if (hooks_parser) {
- hooks_parser->commit();
- }
- }
- catch (const isc::Exception& ex) {
- LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
- answer = isc::config::createAnswer(2,
- string("Configuration commit failed: ") + ex.what());
- rollback = true;
- } catch (...) {
-
- LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_EXCEPTION);
- answer = isc::config::createAnswer(2,
- string("Configuration commit failed"));
- rollback = true;
- }
- }
-
- if (rollback) {
- globalContext().reset(new ParserContext(original_context));
- return (answer);
- }
- LOG_INFO(dhcp4_logger, DHCP4_CONFIG_COMPLETE)
- .arg(CfgMgr::instance().getConfiguration()->
- getConfigSummary(Configuration::CFGSEL_ALL4));
-
- answer = isc::config::createAnswer(0, "Configuration committed.");
- return (answer);
- }
- ParserContextPtr& globalContext() {
- static ParserContextPtr global_context_ptr(new ParserContext(Option::V4));
- return (global_context_ptr);
- }
- };
- };
|