dhcp_parsers.h 42 KB

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