dhcp_parsers.h 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. // Copyright (C) 2013-2016 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. #ifndef DHCP_PARSERS_H
  7. #define DHCP_PARSERS_H
  8. #include <asiolink/io_address.h>
  9. #include <cc/data.h>
  10. #include <dhcp/option_definition.h>
  11. #include <dhcp/option_space_container.h>
  12. #include <dhcpsrv/d2_client_cfg.h>
  13. #include <dhcpsrv/cfg_iface.h>
  14. #include <dhcpsrv/cfg_option.h>
  15. #include <dhcpsrv/subnet.h>
  16. #include <dhcpsrv/parsers/dhcp_config_parser.h>
  17. #include <hooks/libinfo.h>
  18. #include <exceptions/exceptions.h>
  19. #include <util/optional_value.h>
  20. #include <boost/shared_ptr.hpp>
  21. #include <stdint.h>
  22. #include <string>
  23. #include <vector>
  24. namespace isc {
  25. namespace dhcp {
  26. /// Collection of containers holding option spaces. Each container within
  27. /// a particular option space holds so-called option descriptors.
  28. typedef OptionSpaceContainer<OptionContainer, OptionDescriptor,
  29. std::string> OptionStorage;
  30. /// @brief Shared pointer to option storage.
  31. typedef boost::shared_ptr<OptionStorage> OptionStoragePtr;
  32. /// @brief A template class that stores named elements of a given data type.
  33. ///
  34. /// This template class is provides data value storage for configuration
  35. /// parameters of a given data type. The values are stored by parameter name
  36. /// and as instances of type "ValueType". Each value held in the storage has
  37. /// a corresponding position within a configuration string (file) specified
  38. /// as a: file name, line number and position within the line. The position
  39. /// information is used for logging when the particular configuration value
  40. /// causes a configuration error.
  41. ///
  42. /// @tparam ValueType is the data type of the elements to store.
  43. template<typename ValueType>
  44. class ValueStorage {
  45. public:
  46. /// @brief Stores the the parameter, its value and the position in the
  47. /// store.
  48. ///
  49. /// If the parameter does not exist in the store, then it will be added,
  50. /// otherwise its data value and the position will be updated with the
  51. /// given values.
  52. ///
  53. /// @param name is the name of the paramater to store.
  54. /// @param value is the data value to store.
  55. /// @param position is the position of the data element within a
  56. /// configuration string (file).
  57. void setParam(const std::string& name, const ValueType& value,
  58. const data::Element::Position& position) {
  59. values_[name] = value;
  60. positions_[name] = position;
  61. }
  62. /// @brief Returns the data value for the given parameter.
  63. ///
  64. /// Finds and returns the data value for the given parameter.
  65. /// @param name is the name of the parameter for which the data
  66. /// value is desired.
  67. ///
  68. /// @return The paramater's data value of type @c ValueType.
  69. /// @throw DhcpConfigError if the parameter is not found.
  70. ValueType getParam(const std::string& name) const {
  71. typename std::map<std::string, ValueType>::const_iterator param
  72. = values_.find(name);
  73. if (param == values_.end()) {
  74. isc_throw(DhcpConfigError, "Missing parameter '"
  75. << name << "'");
  76. }
  77. return (param->second);
  78. }
  79. /// @brief Returns position of the data element in the configuration string.
  80. ///
  81. /// The returned object comprises file name, line number and the position
  82. /// within the particular line of the configuration string where the data
  83. /// element holding a particular value is located.
  84. ///
  85. /// @param name is the name of the parameter which position is desired.
  86. /// @param parent Pointer to a data element which position should be
  87. /// returned when position of the specified parameter is not found.
  88. ///
  89. /// @return Position of the data element or the position holding empty
  90. /// file name and two zeros if the position hasn't been specified for the
  91. /// particular value.
  92. const data::Element::Position&
  93. getPosition(const std::string& name, const data::ConstElementPtr parent =
  94. data::ConstElementPtr()) const {
  95. typename std::map<std::string, data::Element::Position>::const_iterator
  96. pos = positions_.find(name);
  97. if (pos == positions_.end()) {
  98. return (parent ? parent->getPosition() :
  99. data::Element::ZERO_POSITION());
  100. }
  101. return (pos->second);
  102. }
  103. /// @brief Returns the data value for an optional parameter.
  104. ///
  105. /// Finds and returns the data value for the given parameter or
  106. /// a supplied default value if it is not found.
  107. ///
  108. /// @param name is the name of the parameter for which the data
  109. /// value is desired.
  110. /// @param default_value value to use the default
  111. ///
  112. /// @return The paramater's data value of type @c ValueType.
  113. ValueType getOptionalParam(const std::string& name,
  114. const ValueType& default_value) const {
  115. typename std::map<std::string, ValueType>::const_iterator param
  116. = values_.find(name);
  117. if (param == values_.end()) {
  118. return (default_value);
  119. }
  120. return (param->second);
  121. }
  122. /// @brief Remove the parameter from the store.
  123. ///
  124. /// Deletes the entry for the given parameter from the store if it
  125. /// exists.
  126. ///
  127. /// @param name is the name of the paramater to delete.
  128. void delParam(const std::string& name) {
  129. values_.erase(name);
  130. positions_.erase(name);
  131. }
  132. /// @brief Deletes all of the entries from the store.
  133. ///
  134. void clear() {
  135. values_.clear();
  136. positions_.clear();
  137. }
  138. private:
  139. /// @brief An std::map of the data values, keyed by parameter names.
  140. std::map<std::string, ValueType> values_;
  141. /// @brief An std::map holding positions of the data elements in the
  142. /// configuration, which values are held in @c values_.
  143. ///
  144. /// The position is used for logging, when the particular value
  145. /// causes a configuration error.
  146. std::map<std::string, data::Element::Position> positions_;
  147. };
  148. /// @brief a collection of elements that store uint32 values
  149. typedef ValueStorage<uint32_t> Uint32Storage;
  150. typedef boost::shared_ptr<Uint32Storage> Uint32StoragePtr;
  151. /// @brief a collection of elements that store string values
  152. typedef ValueStorage<std::string> StringStorage;
  153. typedef boost::shared_ptr<StringStorage> StringStoragePtr;
  154. /// @brief Storage for parsed boolean values.
  155. typedef ValueStorage<bool> BooleanStorage;
  156. typedef boost::shared_ptr<BooleanStorage> BooleanStoragePtr;
  157. /// @brief Container for the current parsing context. It provides a
  158. /// single enclosure for the storage of configuration parameters,
  159. /// options, option definitions, and other context specific information
  160. /// that needs to be accessible throughout the parsing and parsing
  161. /// constructs.
  162. class ParserContext {
  163. public:
  164. /// @brief Constructor
  165. ///
  166. /// @param universe is the Option::Universe value of this
  167. /// context.
  168. ParserContext(Option::Universe universe);
  169. /// @brief Copy constructor
  170. ParserContext(const ParserContext& rhs);
  171. /// @brief Storage for boolean parameters.
  172. BooleanStoragePtr boolean_values_;
  173. /// @brief Storage for uint32 parameters.
  174. Uint32StoragePtr uint32_values_;
  175. /// @brief Storage for string parameters.
  176. StringStoragePtr string_values_;
  177. /// @brief Hooks libraries pointer.
  178. ///
  179. /// The hooks libraries information is a vector of strings, each containing
  180. /// the name of a library. Hooks libraries should only be reloaded if the
  181. /// list of names has changed, so the list of current DHCP parameters
  182. /// (in isc::dhcp::CfgMgr) contains an indication as to whether the list has
  183. /// altered. This indication is implemented by storing a pointer to the
  184. /// list of library names which is cleared when the libraries are loaded.
  185. /// So either the pointer is null (meaning don't reload the libraries and
  186. /// the list of current names can be obtained from the HooksManager) or it
  187. /// is non-null (this is the new list of names, reload the libraries when
  188. /// possible).
  189. isc::hooks::HookLibsCollectionPtr hooks_libraries_;
  190. /// @brief The parsing universe of this context.
  191. Option::Universe universe_;
  192. /// @brief Assignment operator
  193. ParserContext& operator=(const ParserContext& rhs);
  194. /// @brief Copy the context fields.
  195. ///
  196. /// This class method initializes the context data by copying the data
  197. /// stored in the context instance provided as an argument. Note that
  198. /// this function will also handle copying the NULL pointers.
  199. ///
  200. /// @param ctx context to be copied.
  201. void copyContext(const ParserContext& ctx);
  202. template<typename T>
  203. void copyContextPointer(const boost::shared_ptr<T>& source_ptr,
  204. boost::shared_ptr<T>& dest_ptr);
  205. };
  206. /// @brief Pointer to various parser context.
  207. typedef boost::shared_ptr<ParserContext> ParserContextPtr;
  208. /// @brief Simple data-type parser template class
  209. ///
  210. /// This is the template class for simple data-type parsers. It supports
  211. /// parsing a configuration parameter with specific data-type for its
  212. /// possible values. It provides a common constructor, commit, and templated
  213. /// data storage. The "build" method implementation must be provided by a
  214. /// declaring type.
  215. /// @param ValueType is the data type of the configuration paramater value
  216. /// the parser should handle.
  217. template<typename ValueType>
  218. class ValueParser : public DhcpConfigParser {
  219. public:
  220. /// @brief Constructor.
  221. ///
  222. /// @param param_name name of the parameter.
  223. /// @param storage is a pointer to the storage container where the parsed
  224. /// value be stored upon commit.
  225. /// @throw isc::dhcp::DhcpConfigError if a provided parameter's
  226. /// name is empty.
  227. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  228. ValueParser(const std::string& param_name,
  229. boost::shared_ptr<ValueStorage<ValueType> > storage)
  230. : storage_(storage), param_name_(param_name), value_(), pos_() {
  231. // Empty parameter name is invalid.
  232. if (param_name_.empty()) {
  233. isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
  234. << "empty parameter name provided");
  235. }
  236. // NUll storage is invalid.
  237. if (!storage_) {
  238. isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
  239. << "storage may not be NULL");
  240. }
  241. }
  242. /// @brief Parse a given element into a value of type @c ValueType
  243. ///
  244. /// @param value a value to be parsed.
  245. ///
  246. /// @throw isc::BadValue Typically the implementing type will throw
  247. /// a BadValue exception when given an invalid Element to parse.
  248. void build(isc::data::ConstElementPtr value);
  249. /// @brief Put a parsed value to the storage.
  250. void commit() {
  251. // If a given parameter already exists in the storage we override
  252. // its value. If it doesn't we insert a new element.
  253. storage_->setParam(param_name_, value_, pos_);
  254. }
  255. private:
  256. /// @brief Performs operations common for all specializations of the
  257. /// @c build function.
  258. ///
  259. /// This method should be called by all specializations of the @c build
  260. /// method.
  261. ///
  262. /// @param value a value being parsed.
  263. void buildCommon(isc::data::ConstElementPtr value) {
  264. // Remember position of the data element.
  265. pos_ = value->getPosition();
  266. }
  267. /// Pointer to the storage where committed value is stored.
  268. boost::shared_ptr<ValueStorage<ValueType> > storage_;
  269. /// Name of the parameter which value is parsed with this parser.
  270. std::string param_name_;
  271. /// Parsed value.
  272. ValueType value_;
  273. data::Element::Position pos_;
  274. };
  275. /// @brief typedefs for simple data type parsers
  276. typedef ValueParser<bool> BooleanParser;
  277. typedef ValueParser<uint32_t> Uint32Parser;
  278. typedef ValueParser<std::string> StringParser;
  279. /// @brief a dummy configuration parser
  280. ///
  281. /// It is a debugging parser. It does not configure anything,
  282. /// will accept any configuration and will just print it out
  283. /// on commit. Useful for debugging existing configurations and
  284. /// adding new ones.
  285. class DebugParser : public DhcpConfigParser {
  286. public:
  287. /// @brief Constructor
  288. ///
  289. /// See @ref DhcpConfigParser class for details.
  290. ///
  291. /// @param param_name name of the parsed parameter
  292. DebugParser(const std::string& param_name);
  293. /// @brief builds parameter value
  294. ///
  295. /// See @ref DhcpConfigParser class for details.
  296. ///
  297. /// @param new_config pointer to the new configuration
  298. virtual void build(isc::data::ConstElementPtr new_config);
  299. /// @brief pretends to apply the configuration
  300. ///
  301. /// This is a method required by base class. It pretends to apply the
  302. /// configuration, but in fact it only prints the parameter out.
  303. ///
  304. /// See @ref DhcpConfigParser class for details.
  305. virtual void commit();
  306. private:
  307. /// name of the parsed parameter
  308. std::string param_name_;
  309. /// pointer to the actual value of the parameter
  310. isc::data::ConstElementPtr value_;
  311. };
  312. /// @brief parser for MAC/hardware aquisition sources
  313. ///
  314. /// This parser handles Dhcp6/mac-sources entry.
  315. /// It contains a list of MAC/hardware aquisition source, i.e. methods how
  316. /// MAC address can possibly by obtained in DHCPv6. For a currently supported
  317. /// methods, see @ref isc::dhcp::Pkt::getMAC.
  318. class MACSourcesListConfigParser : public DhcpConfigParser {
  319. public:
  320. /// @brief constructor
  321. ///
  322. /// As this is a dedicated parser, it must be used to parse
  323. /// "mac-sources" parameter only. All other types will throw exception.
  324. ///
  325. /// @param param_name name of the configuration parameter being parsed
  326. /// @param global_context Global parser context.
  327. /// @throw BadValue if supplied parameter name is not "mac-sources"
  328. MACSourcesListConfigParser(const std::string& param_name,
  329. ParserContextPtr global_context);
  330. /// @brief parses parameters value
  331. ///
  332. /// Parses configuration entry (list of sources) and adds each element
  333. /// to the sources list.
  334. ///
  335. /// @param value pointer to the content of parsed values
  336. virtual void build(isc::data::ConstElementPtr value);
  337. /// @brief Does nothing.
  338. virtual void commit();
  339. private:
  340. // Parsed parameter name
  341. std::string param_name_;
  342. /// Global parser context.
  343. ParserContextPtr global_context_;
  344. };
  345. /// @brief Parser for the control-socket structure
  346. ///
  347. /// It does not parse anything, simply stores the element in
  348. /// the staging config.
  349. class ControlSocketParser : public DhcpConfigParser {
  350. public:
  351. ControlSocketParser(const std::string& param_name);
  352. /// @brief Stores contents of the control-socket map in the staging config.
  353. ///
  354. /// @param value pointer to the content of parsed values
  355. virtual void build(isc::data::ConstElementPtr value);
  356. /// @brief Does nothing.
  357. virtual void commit();
  358. };
  359. /// @brief Parser for hooks library list
  360. ///
  361. /// This parser handles the list of hooks libraries. This is an optional list,
  362. /// which may be empty.
  363. ///
  364. /// However, the parser does more than just check the list of library names.
  365. /// It does two other things:
  366. ///
  367. /// -# The problem faced with the hooks libraries is that we wish to avoid
  368. /// reloading the libraries if they have not changed. (This would cause the
  369. /// "unload" and "load" methods to run. Although libraries should be written
  370. /// to cope with this, it is feasible that such an action may be constly in
  371. /// terms of time and resources, or may cause side effects such as clearning
  372. /// an internal cache.) To this end, the parser also checks the list against
  373. /// the list of libraries current loaded and notes if there are changes.
  374. /// -# If there are, the parser validates the libraries; it opens them and
  375. /// checks that the "version" function exists and returns the correct value.
  376. ///
  377. /// Only if the library list has changed and the libraries are valid will the
  378. /// change be applied.
  379. class HooksLibrariesParser : public DhcpConfigParser {
  380. public:
  381. /// @brief Constructor
  382. ///
  383. /// As this is a dedicated parser, it must be used to parse
  384. /// "hooks-libraries" parameter only. All other types will throw exception.
  385. ///
  386. /// @param param_name name of the configuration parameter being parsed.
  387. ///
  388. /// @throw BadValue if supplied parameter name is not "hooks-libraries"
  389. HooksLibrariesParser(const std::string& param_name);
  390. /// @brief Parses parameters value
  391. ///
  392. /// Parses configuration entry (list of parameters) and adds each element
  393. /// to the hooks libraries list. The method also checks whether the
  394. /// list of libraries is the same as that already loaded. If not, it
  395. /// checks each of the libraries in the list for validity (they exist and
  396. /// have a "version" function that returns the correct value).
  397. ///
  398. /// The syntax for specifying hooks libraries allow for library-specific
  399. /// parameters to be specified along with the library, e.g.
  400. ///
  401. /// @code
  402. /// "hooks-libraries": [
  403. /// {
  404. /// "library": "hook-lib-1.so",
  405. /// "parameters": {
  406. /// "alpha": "a string",
  407. /// "beta": 42
  408. /// }
  409. /// },
  410. /// :
  411. /// ]
  412. /// @endcode
  413. ///
  414. /// As Kea has not yet implemented parameters, the parsing code only checks
  415. /// that:
  416. ///
  417. /// -# Each element in the hooks-libraries list is a map
  418. /// -# The map contains an element "library" whose value is a string: all
  419. /// other elements in the map are ignored.
  420. ///
  421. /// @param value pointer to the content of parsed values
  422. virtual void build(isc::data::ConstElementPtr value);
  423. /// @brief Commits hooks libraries data
  424. ///
  425. /// Providing that the specified libraries are valid and are different
  426. /// to those already loaded, this method loads the new set of libraries
  427. /// (and unloads the existing set).
  428. virtual void commit();
  429. /// @brief Returns list of parsed libraries
  430. ///
  431. /// Principally for testing, this returns the list of libraries as well as
  432. /// an indication as to whether the list is different from the list of
  433. /// libraries already loaded.
  434. ///
  435. /// @param [out] libraries List of libraries that were specified in the
  436. /// new configuration.
  437. /// @param [out] changed true if the list is different from that currently
  438. /// loaded.
  439. void getLibraries(isc::hooks::HookLibsCollection& libraries, bool& changed);
  440. private:
  441. /// List of hooks libraries with their configuration parameters
  442. isc::hooks::HookLibsCollection libraries_;
  443. /// Indicator flagging that the list of libraries has changed.
  444. bool changed_;
  445. };
  446. /// @brief Parser for option data value.
  447. ///
  448. /// This parser parses configuration entries that specify value of
  449. /// a single option. These entries include option name, option code
  450. /// and data carried by the option. The option data can be specified
  451. /// in one of the two available formats: binary value represented as
  452. /// a string of hexadecimal digits or a list of comma separated values.
  453. /// The format being used is controlled by csv-format configuration
  454. /// parameter. When setting this value to True, the latter format is
  455. /// used. The subsequent values in the CSV format apply to relevant
  456. /// option data fields in the configured option. For example the
  457. /// configuration: "data" : "192.168.2.0, 56, hello world" can be
  458. /// used to set values for the option comprising IPv4 address,
  459. /// integer and string data field. Note that order matters. If the
  460. /// order of values does not match the order of data fields within
  461. /// an option the configuration will not be accepted. If parsing
  462. /// is successful then an instance of an option is created and
  463. /// added to the storage provided by the calling class.
  464. class OptionDataParser : public DhcpConfigParser {
  465. public:
  466. /// @brief Constructor.
  467. ///
  468. /// @param dummy first argument is ignored, all Parser constructors
  469. /// accept string as first argument.
  470. /// @param [out] cfg Pointer to the configuration object where parsed option
  471. /// should be stored or NULL if this is a global option.
  472. /// @param address_family Address family: @c AF_INET or @c AF_INET6.
  473. /// @throw isc::dhcp::DhcpConfigError if options or global_context are null.
  474. OptionDataParser(const std::string& dummy, const CfgOptionPtr& cfg,
  475. const uint16_t address_family);
  476. /// @brief Parses the single option data.
  477. ///
  478. /// This method parses the data of a single option from the configuration.
  479. /// The option data includes option name, option code and data being
  480. /// carried by this option. Eventually it creates the instance of the
  481. /// option and adds it to the Configuration Manager.
  482. ///
  483. /// @param option_data_entries collection of entries that define value
  484. /// for a particular option.
  485. /// @throw DhcpConfigError if invalid parameter specified in
  486. /// the configuration.
  487. /// @throw isc::InvalidOperation if failed to set storage prior to
  488. /// calling build.
  489. virtual void build(isc::data::ConstElementPtr option_data_entries);
  490. /// @brief Does nothing.
  491. virtual void commit();
  492. /// @brief virtual destructor to ensure orderly destruction of derivations.
  493. virtual ~OptionDataParser(){};
  494. private:
  495. /// @brief Finds an option definition within an option space
  496. ///
  497. /// Given an option space and an option code, find the correpsonding
  498. /// option defintion within the option defintion storage.
  499. ///
  500. /// @param option_space name of the parameter option space
  501. /// @param search_key an option code or name to be used to lookup the
  502. /// option definition.
  503. /// @tparam A numeric type for searching using an option code or the
  504. /// string for searching using the option name.
  505. ///
  506. /// @return OptionDefintionPtr of the option defintion or an
  507. /// empty OptionDefinitionPtr if not found.
  508. /// @throw DhcpConfigError if the option space requested is not valid
  509. /// for this server.
  510. template<typename SearchKey>
  511. OptionDefinitionPtr findOptionDefinition(const std::string& option_space,
  512. const SearchKey& search_key) const;
  513. /// @brief Create option instance.
  514. ///
  515. /// Creates an instance of an option and adds it to the provided
  516. /// options storage. If the option data parsed by \ref build function
  517. /// are invalid or insufficient this function emits an exception.
  518. ///
  519. /// @warning this function does not check if options_ storage pointer
  520. /// is intitialized but this check is not needed here because it is done
  521. /// in the \ref build function.
  522. ///
  523. /// @param option_data An element holding data for a single option being
  524. /// created.
  525. ///
  526. /// @throw DhcpConfigError if parameters provided in the configuration
  527. /// are invalid.
  528. void createOption(isc::data::ConstElementPtr option_data);
  529. /// @brief Retrieves parsed option code as an optional value.
  530. ///
  531. /// @param parent A data element holding full option data configuration.
  532. /// It is used here to log a position if the element holding a code
  533. /// is not specified and its position is therefore unavailable.
  534. ///
  535. /// @return Option code, possibly unspecified.
  536. /// @throw DhcpConfigError if option code is invalid.
  537. util::OptionalValue<uint32_t>
  538. extractCode(data::ConstElementPtr parent) const;
  539. /// @brief Retrieves parsed option name as an optional value.
  540. ///
  541. /// @param parent A data element holding full option data configuration.
  542. /// It is used here to log a position if the element holding a name
  543. /// is not specified and its position is therefore unavailable.
  544. ///
  545. /// @return Option name, possibly unspecified.
  546. /// @throw DhcpConfigError if option name is invalid.
  547. util::OptionalValue<std::string>
  548. extractName(data::ConstElementPtr parent) const;
  549. /// @brief Retrieves csv-format parameter as an optional value.
  550. ///
  551. /// @return Value of the csv-format parameter, possibly unspecified.
  552. util::OptionalValue<bool> extractCSVFormat() const;
  553. /// @brief Retrieves option data as a string.
  554. ///
  555. /// @return Option data as a string. It will return empty string if
  556. /// option data is unspecified.
  557. std::string extractData() const;
  558. /// @brief Retrieves option space name.
  559. ///
  560. /// If option space name is not specified in the configuration the
  561. /// 'dhcp4' or 'dhcp6' option space name is returned, depending on
  562. /// the universe specified in the parser context.
  563. ///
  564. /// @return Option space name.
  565. std::string extractSpace() const;
  566. /// Storage for boolean values.
  567. BooleanStoragePtr boolean_values_;
  568. /// Storage for string values (e.g. option name or data).
  569. StringStoragePtr string_values_;
  570. /// Storage for uint32 values (e.g. option code).
  571. Uint32StoragePtr uint32_values_;
  572. /// Option descriptor holds newly configured option.
  573. OptionDescriptor option_descriptor_;
  574. /// Option space name where the option belongs to.
  575. std::string option_space_;
  576. /// @brief Configuration holding option being parsed or NULL if the option
  577. /// is global.
  578. CfgOptionPtr cfg_;
  579. /// @brief Address family: @c AF_INET or @c AF_INET6.
  580. uint16_t address_family_;
  581. };
  582. ///@brief Function pointer for OptionDataParser factory methods
  583. typedef OptionDataParser *OptionDataParserFactory(const std::string&,
  584. OptionStoragePtr options, ParserContextPtr global_context);
  585. /// @brief Parser for option data values within a subnet.
  586. ///
  587. /// This parser iterates over all entries that define options
  588. /// data for a particular subnet and creates a collection of options.
  589. /// If parsing is successful, all these options are added to the Subnet
  590. /// object.
  591. class OptionDataListParser : public DhcpConfigParser {
  592. public:
  593. /// @brief Constructor.
  594. ///
  595. /// @param dummy nominally would be param name, this is always ignored.
  596. /// @param [out] cfg Pointer to the configuration object where options
  597. /// should be stored or NULL if this is global option scope.
  598. /// @param address_family Address family: @c AF_INET or AF_INET6
  599. OptionDataListParser(const std::string& dummy, const CfgOptionPtr& cfg,
  600. const uint16_t address_family);
  601. /// @brief Parses entries that define options' data for a subnet.
  602. ///
  603. /// This method iterates over all entries that define option data
  604. /// for options within a single subnet and creates options' instances.
  605. ///
  606. /// @param option_data_list pointer to a list of options' data sets.
  607. /// @throw DhcpConfigError if option parsing failed.
  608. void build(isc::data::ConstElementPtr option_data_list);
  609. /// @brief Commit all option values.
  610. ///
  611. /// This function invokes commit for all option values
  612. /// and append suboptions to the top-level options.
  613. void commit();
  614. private:
  615. /// Collection of parsers;
  616. ParserCollection parsers_;
  617. /// @brief Pointer to a configuration where options are stored.
  618. CfgOptionPtr cfg_;
  619. /// @brief Address family: @c AF_INET or @c AF_INET6
  620. uint16_t address_family_;
  621. };
  622. typedef boost::shared_ptr<OptionDataListParser> OptionDataListParserPtr;
  623. /// @brief Parser for a single option definition.
  624. ///
  625. /// This parser creates an instance of a single option definition.
  626. class OptionDefParser : public DhcpConfigParser {
  627. public:
  628. /// @brief Constructor.
  629. ///
  630. /// @param dummy first argument is ignored, all Parser constructors
  631. /// accept string as first argument.
  632. /// @param global_context is a pointer to the global context which
  633. /// stores global scope parameters, options, option defintions.
  634. OptionDefParser(const std::string& dummy, ParserContextPtr global_context);
  635. /// @brief Parses an entry that describes single option definition.
  636. ///
  637. /// @param option_def a configuration entry to be parsed.
  638. ///
  639. /// @throw DhcpConfigError if parsing was unsuccessful.
  640. void build(isc::data::ConstElementPtr option_def);
  641. /// @brief Stores the parsed option definition in a storage.
  642. void commit();
  643. private:
  644. /// @brief Create option definition from the parsed parameters.
  645. ///
  646. /// @param option_def_element A data element holding the configuration
  647. /// for an option definition.
  648. void createOptionDef(isc::data::ConstElementPtr option_def_element);
  649. /// Instance of option definition being created by this parser.
  650. OptionDefinitionPtr option_definition_;
  651. /// Name of the space the option definition belongs to.
  652. std::string option_space_name_;
  653. /// Storage for boolean values.
  654. BooleanStoragePtr boolean_values_;
  655. /// Storage for string values.
  656. StringStoragePtr string_values_;
  657. /// Storage for uint32 values.
  658. Uint32StoragePtr uint32_values_;
  659. /// Parsing context which contains global values, options and option
  660. /// definitions.
  661. ParserContextPtr global_context_;
  662. };
  663. /// @brief Parser for a list of option definitions.
  664. ///
  665. /// This parser iterates over all configuration entries that define
  666. /// option definitions and creates instances of these definitions.
  667. /// If the parsing is successful, the collection of created definitions
  668. /// is put into the provided storage.
  669. class OptionDefListParser : public DhcpConfigParser {
  670. public:
  671. /// @brief Constructor.
  672. ///
  673. /// @param dummy first argument is ignored, all Parser constructors
  674. /// accept string as first argument.
  675. /// @param global_context is a pointer to the global context which
  676. /// stores global scope parameters, options, option defintions.
  677. OptionDefListParser(const std::string& dummy,
  678. ParserContextPtr global_context);
  679. /// @brief Parse configuration entries.
  680. ///
  681. /// This function parses configuration entries, creates instances
  682. /// of option definitions and tries to add them to the Configuration
  683. /// Manager.
  684. ///
  685. /// @param option_def_list pointer to an element that holds entries
  686. /// that define option definitions.
  687. /// @throw DhcpConfigError if configuration parsing fails.
  688. void build(isc::data::ConstElementPtr option_def_list);
  689. /// @brief Commits option definitions.
  690. ///
  691. /// Currently this function is no-op, because option definitions are
  692. /// added to the Configuration Manager in the @c build method.
  693. void commit();
  694. /// Parsing context which contains global values, options and option
  695. /// definitions.
  696. ParserContextPtr global_context_;
  697. };
  698. /// @brief a collection of pools
  699. ///
  700. /// That type is used as intermediate storage, when pools are parsed, but there is
  701. /// no subnet object created yet to store them.
  702. typedef std::vector<PoolPtr> PoolStorage;
  703. typedef boost::shared_ptr<PoolStorage> PoolStoragePtr;
  704. /// @brief parser for a single pool definition
  705. ///
  706. /// This abstract parser handles pool definitions, i.e. a list of entries of one
  707. /// of two syntaxes: min-max and prefix/len. Pool objects are created
  708. /// and stored in chosen PoolStorage container.
  709. ///
  710. /// It is useful for parsing Dhcp<4/6>/subnet<4/6>[X]/pools[X] structure.
  711. class PoolParser : public DhcpConfigParser {
  712. public:
  713. /// @brief constructor.
  714. ///
  715. /// @param dummy first argument is ignored, all Parser constructors
  716. /// accept string as first argument.
  717. /// @param pools is the storage in which to store the parsed pool
  718. /// upon "commit".
  719. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  720. PoolParser(const std::string& dummy, PoolStoragePtr pools);
  721. /// @brief parses the actual structure
  722. ///
  723. /// This method parses the actual list of interfaces.
  724. /// No validation is done at this stage, everything is interpreted as
  725. /// interface name.
  726. /// @param pool_structure a single entry on a list of pools
  727. /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
  728. virtual void build(isc::data::ConstElementPtr pool_structure);
  729. /// @brief Stores the parsed values in a storage provided
  730. /// by an upper level parser.
  731. virtual void commit();
  732. protected:
  733. /// @brief Creates a Pool object given a IPv4 prefix and the prefix length.
  734. ///
  735. /// @param addr is the IP prefix of the pool.
  736. /// @param len is the prefix length.
  737. /// @param ptype is the type of pool to create.
  738. /// @return returns a PoolPtr to the new Pool object.
  739. virtual PoolPtr poolMaker(isc::asiolink::IOAddress &addr, uint32_t len,
  740. int32_t ptype=0) = 0;
  741. /// @brief Creates a Pool object given starting and ending IP addresses.
  742. ///
  743. /// @param min is the first IP address in the pool.
  744. /// @param max is the last IP address in the pool.
  745. /// @param ptype is the type of pool to create (not used by all derivations)
  746. /// @return returns a PoolPtr to the new Pool object.
  747. virtual PoolPtr poolMaker(isc::asiolink::IOAddress &min,
  748. isc::asiolink::IOAddress &max, int32_t ptype=0) = 0;
  749. /// @brief pointer to the actual Pools storage
  750. ///
  751. /// That is typically a storage somewhere in Subnet parser
  752. /// (an upper level parser).
  753. PoolStoragePtr pools_;
  754. /// A temporary storage for pools configuration. It is a
  755. /// storage where pools are stored by build function.
  756. PoolStorage local_pools_;
  757. /// A storage for pool specific option values.
  758. CfgOptionPtr options_;
  759. };
  760. /// @brief Parser for a list of pools
  761. ///
  762. /// This parser parses a list pools. Each element on that list gets its own
  763. /// parser, created with poolParserMaker() method. That method must be specified
  764. /// for each protocol family (v4 or v6) separately.
  765. ///
  766. /// This class is not intended to be used directly. Instead, derived classes
  767. /// should implement poolParserMaker() method.
  768. class PoolsListParser : public DhcpConfigParser {
  769. public:
  770. /// @brief constructor.
  771. ///
  772. /// @param dummy first argument is ignored, all Parser constructors
  773. /// accept a string as the first argument.
  774. /// @param pools is the storage in which to store the parsed pool
  775. /// upon "commit".
  776. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  777. PoolsListParser(const std::string& dummy, PoolStoragePtr pools);
  778. /// @brief parses the actual structure
  779. ///
  780. /// This method parses the actual list of pools. It creates a parser
  781. /// for each structure using poolParserMaker().
  782. ///
  783. /// @param pools_list a list of pool structures
  784. /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
  785. virtual void build(isc::data::ConstElementPtr pools_list);
  786. /// @brief Stores the parsed values in storage provided
  787. /// by an upper level parser.
  788. virtual void commit();
  789. protected:
  790. /// @brief Creates a PoolParser object
  791. ///
  792. /// Instantiates appropriate (v4 or v6) PoolParser object.
  793. /// @param storage parameter that is passed to ParserMaker() constructor.
  794. virtual ParserPtr poolParserMaker(PoolStoragePtr storage) = 0;
  795. /// @brief pointer to the actual Pools storage
  796. ///
  797. /// That is typically a storage somewhere in Subnet parser
  798. /// (an upper level parser).
  799. PoolStoragePtr pools_;
  800. /// A temporary storage for pools configuration. It is the
  801. /// storage where pools are stored by the build function.
  802. PoolStoragePtr local_pools_;
  803. /// Collection of parsers;
  804. ParserCollection parsers_;
  805. };
  806. /// @brief parser for additional relay information
  807. ///
  808. /// This concrete parser handles RelayInfo structure defintions.
  809. /// So far that structure holds only relay IP (v4 or v6) address, but it
  810. /// is expected that the number of parameters will increase over time.
  811. ///
  812. /// It is useful for parsing Dhcp<4/6>/subnet<4/6>[x]/relay parameters.
  813. class RelayInfoParser : public DhcpConfigParser {
  814. public:
  815. /// @brief constructor
  816. /// @param unused first argument is ignored, all Parser constructors
  817. /// accept string as first argument.
  818. /// @param relay_info is the storage in which to store the parsed
  819. /// @param family specifies protocol family (IPv4 or IPv6)
  820. RelayInfoParser(const std::string& unused,
  821. const isc::dhcp::Subnet::RelayInfoPtr& relay_info,
  822. const isc::dhcp::Option::Universe& family);
  823. /// @brief parses the actual relay parameters
  824. /// @param relay_info JSON structure holding relay parameters to parse
  825. virtual void build(isc::data::ConstElementPtr relay_info);
  826. /// @brief stores parsed info in relay_info
  827. virtual void commit();
  828. protected:
  829. /// @brief Creates a parser for the given "relay" member element id.
  830. ///
  831. /// The elements currently supported are:
  832. /// -# ip-address
  833. ///
  834. /// @param parser is the "item_name" for a specific member element of
  835. /// the "relay" specification.
  836. ///
  837. /// @return returns a pointer to newly created parser.
  838. isc::dhcp::ParserPtr
  839. createConfigParser(const std::string& parser);
  840. /// Parsed data will be stored there on commit()
  841. isc::dhcp::Subnet::RelayInfoPtr storage_;
  842. /// Local storage information (for temporary values)
  843. isc::dhcp::Subnet::RelayInfo local_;
  844. /// Storage for subnet-specific string values.
  845. StringStoragePtr string_values_;
  846. /// Protocol family (IPv4 or IPv6)
  847. Option::Universe family_;
  848. };
  849. /// @brief this class parses a single subnet
  850. ///
  851. /// This class parses the whole subnet definition. It creates parsers
  852. /// for received configuration parameters as needed.
  853. class SubnetConfigParser : public DhcpConfigParser {
  854. public:
  855. /// @brief constructor
  856. ///
  857. /// @param global_context
  858. /// @param default_addr default IP address (0.0.0.0 for IPv4, :: for IPv6)
  859. SubnetConfigParser(const std::string&, ParserContextPtr global_context,
  860. const isc::asiolink::IOAddress& default_addr);
  861. /// @brief parses parameter value
  862. ///
  863. /// @param subnet pointer to the content of subnet definition
  864. ///
  865. /// @throw isc::DhcpConfigError if subnet configuration parsing failed.
  866. virtual void build(isc::data::ConstElementPtr subnet);
  867. /// @brief Adds the created subnet to a server's configuration.
  868. virtual void commit() = 0;
  869. protected:
  870. /// @brief creates parsers for entries in subnet definition
  871. ///
  872. /// @param config_id name od the entry
  873. ///
  874. /// @return parser object for specified entry name
  875. /// @throw isc::dhcp::DhcpConfigError if trying to create a parser
  876. /// for unknown config element
  877. virtual DhcpConfigParser* createSubnetConfigParser(
  878. const std::string& config_id) = 0;
  879. /// @brief Issues a server specific warning regarding duplicate subnet
  880. /// options.
  881. ///
  882. /// @param code is the numeric option code of the duplicate option
  883. /// @param addr is the subnet address
  884. /// @todo a means to know the correct logger and perhaps a common
  885. /// message would allow this method to be emitted by the base class.
  886. virtual void duplicate_option_warning(uint32_t code,
  887. isc::asiolink::IOAddress& addr) = 0;
  888. /// @brief Instantiates the subnet based on a given IP prefix and prefix
  889. /// length.
  890. ///
  891. /// @param addr is the IP prefix of the subnet.
  892. /// @param len is the prefix length
  893. virtual void initSubnet(isc::asiolink::IOAddress addr, uint8_t len) = 0;
  894. /// @brief Returns value for a given parameter (after using inheritance)
  895. ///
  896. /// This method implements inheritance. For a given parameter name, it first
  897. /// checks if there is a global value for it and overwrites it with specific
  898. /// value if such value was defined in subnet.
  899. ///
  900. /// @param name name of the parameter
  901. /// @return triplet with the parameter name
  902. /// @throw DhcpConfigError when requested parameter is not present
  903. isc::dhcp::Triplet<uint32_t> getParam(const std::string& name);
  904. /// @brief Returns optional value for a given parameter.
  905. ///
  906. /// This method checks if an optional parameter has been specified for
  907. /// a subnet. If not, it will try to use a global value. If the global
  908. /// value is not specified it will return an object representing an
  909. /// unspecified value.
  910. ///
  911. /// @param name name of the configuration parameter.
  912. /// @return An optional value or a @c Triplet object representing
  913. /// unspecified value.
  914. isc::dhcp::Triplet<uint32_t> getOptionalParam(const std::string& name);
  915. /// @brief Attempts to convert text representation to HRMode enum.
  916. ///
  917. /// Allowed values are "disabled", "off" (alias for disabled),
  918. /// "out-of-pool" and "all". See Subnet::HRMode for their exact meaning.
  919. ///
  920. /// @param txt Host Reservation mode in the textual form.
  921. ///
  922. /// @throw BadValue if the text cannot be converted.
  923. ///
  924. /// @return one of allowed HRMode values
  925. static Subnet::HRMode hrModeFromText(const std::string& txt);
  926. private:
  927. /// @brief Create a new subnet using a data from child parsers.
  928. ///
  929. /// @throw isc::dhcp::DhcpConfigError if subnet configuration parsing
  930. /// failed.
  931. void createSubnet();
  932. protected:
  933. /// Storage for subnet-specific integer values.
  934. Uint32StoragePtr uint32_values_;
  935. /// Storage for subnet-specific string values.
  936. StringStoragePtr string_values_;
  937. /// Storage for subnet-specific boolean values.
  938. BooleanStoragePtr boolean_values_;
  939. /// Storage for pools belonging to this subnet.
  940. PoolStoragePtr pools_;
  941. /// Parsers are stored here.
  942. ParserCollection parsers_;
  943. /// Pointer to the created subnet object.
  944. isc::dhcp::SubnetPtr subnet_;
  945. /// Parsing context which contains global values, options and option
  946. /// definitions.
  947. ParserContextPtr global_context_;
  948. /// Pointer to relay information
  949. isc::dhcp::Subnet::RelayInfoPtr relay_info_;
  950. /// Pointer to the options configuration.
  951. CfgOptionPtr options_;
  952. };
  953. /// @brief Parser for D2ClientConfig
  954. ///
  955. /// This class parses the configuration element "dhcp-ddns" common to the
  956. /// spec files for both dhcp4 and dhcp6. It creates an instance of a
  957. /// D2ClientConfig.
  958. class D2ClientConfigParser : public isc::dhcp::DhcpConfigParser {
  959. public:
  960. /// @brief Constructor
  961. ///
  962. /// @param entry_name is an arbitrary label assigned to this configuration
  963. /// definition.
  964. D2ClientConfigParser(const std::string& entry_name);
  965. /// @brief Destructor
  966. virtual ~D2ClientConfigParser();
  967. /// @brief Performs the parsing of the given dhcp-ddns element.
  968. ///
  969. /// The results of the parsing are retained internally for use during
  970. /// commit.
  971. /// @todo This parser supplies hard-coded default values for all
  972. /// optional parameters. This should be changed once a new plan
  973. /// for configuration is determined.
  974. ///
  975. /// @param client_config is the "dhcp-ddns" configuration to parse
  976. virtual void build(isc::data::ConstElementPtr client_config);
  977. /// @brief Creates a parser for the given "dhcp-ddns" member element id.
  978. ///
  979. /// The elements currently supported are (see isc::dhcp::D2ClientConfig
  980. /// for details on each):
  981. /// -# enable-updates
  982. /// -# qualifying-suffix
  983. /// -# server-ip
  984. /// -# server-port
  985. /// -# ncr-protocol
  986. /// -# ncr-format
  987. /// -# remove-on-renew
  988. /// -# always-include-fqdn
  989. /// -# allow-client-update
  990. /// -# override-no-update
  991. /// -# override-client-update
  992. /// -# replace-client-name
  993. /// -# generated-prefix
  994. ///
  995. /// @param config_id is the "item_name" for a specific member element of
  996. /// the "dns_server" specification.
  997. ///
  998. /// @return returns a pointer to newly created parser.
  999. virtual isc::dhcp::ParserPtr createConfigParser(const std::string&
  1000. config_id);
  1001. /// @brief Instantiates a D2ClientConfig from internal data values
  1002. /// passes to CfgMgr singleton.
  1003. virtual void commit();
  1004. private:
  1005. /// @brief Arbitrary label assigned to this parser instance.
  1006. /// Primarily used for diagnostics.
  1007. std::string entry_name_;
  1008. /// Storage for subnet-specific boolean values.
  1009. BooleanStoragePtr boolean_values_;
  1010. /// Storage for subnet-specific integer values.
  1011. Uint32StoragePtr uint32_values_;
  1012. /// Storage for subnet-specific string values.
  1013. StringStoragePtr string_values_;
  1014. /// @brief Pointer to temporary local instance created during build.
  1015. D2ClientConfigPtr local_client_config_ ;
  1016. };
  1017. // Pointers to various parser objects.
  1018. typedef boost::shared_ptr<BooleanParser> BooleanParserPtr;
  1019. typedef boost::shared_ptr<StringParser> StringParserPtr;
  1020. typedef boost::shared_ptr<Uint32Parser> Uint32ParserPtr;
  1021. }; // end of isc::dhcp namespace
  1022. }; // end of isc namespace
  1023. #endif // DHCP_PARSERS_H