dhcp_parsers.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. // Copyright (C) 2013 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.h>
  20. #include <dhcpsrv/dhcp_config_parser.h>
  21. #include <dhcpsrv/option_space_container.h>
  22. #include <dhcpsrv/subnet.h>
  23. #include <exceptions/exceptions.h>
  24. #include <boost/shared_ptr.hpp>
  25. #include <stdint.h>
  26. #include <string>
  27. #include <vector>
  28. namespace isc {
  29. namespace dhcp {
  30. /// @brief Storage for option definitions.
  31. typedef OptionSpaceContainer<OptionDefContainer,
  32. OptionDefinitionPtr, std::string> OptionDefStorage;
  33. /// @brief Shared pointer to option definitions storage.
  34. typedef boost::shared_ptr<OptionDefStorage> OptionDefStoragePtr;
  35. /// Collection of containers holding option spaces. Each container within
  36. /// a particular option space holds so-called option descriptors.
  37. typedef OptionSpaceContainer<Subnet::OptionContainer,
  38. Subnet::OptionDescriptor, std::string> OptionStorage;
  39. /// @brief Shared pointer to option storage.
  40. typedef boost::shared_ptr<OptionStorage> OptionStoragePtr;
  41. /// @brief Shared pointer to collection of hooks libraries.
  42. typedef boost::shared_ptr<std::vector<std::string> > HooksLibsStoragePtr;
  43. /// @brief A template class that stores named elements of a given data type.
  44. ///
  45. /// This template class is provides data value storage for configuration parameters
  46. /// of a given data type. The values are stored by parameter name and as instances
  47. /// of type "ValueType".
  48. ///
  49. /// @param ValueType is the data type of the elements to store.
  50. template<typename ValueType>
  51. class ValueStorage {
  52. public:
  53. /// @brief Stores the the parameter and its value in the store.
  54. ///
  55. /// If the parameter does not exist in the store, then it will be added,
  56. /// otherwise its data value will be updated with the given value.
  57. ///
  58. /// @param name is the name of the paramater to store.
  59. /// @param value is the data value to store.
  60. void setParam(const std::string& name, const ValueType& value) {
  61. values_[name] = value;
  62. }
  63. /// @brief Returns the data value for the given parameter.
  64. ///
  65. /// Finds and returns the data value for the given parameter.
  66. /// @param name is the name of the parameter for which the data
  67. /// value is desired.
  68. ///
  69. /// @return The paramater's data value of type @c ValueType.
  70. /// @throw DhcpConfigError if the parameter is not found.
  71. ValueType getParam(const std::string& name) const {
  72. typename std::map<std::string, ValueType>::const_iterator param
  73. = values_.find(name);
  74. if (param == values_.end()) {
  75. isc_throw(DhcpConfigError, "Missing parameter '"
  76. << name << "'");
  77. }
  78. return (param->second);
  79. }
  80. /// @brief Remove the parameter from the store.
  81. ///
  82. /// Deletes the entry for the given parameter from the store if it
  83. /// exists.
  84. ///
  85. /// @param name is the name of the paramater to delete.
  86. void delParam(const std::string& name) {
  87. values_.erase(name);
  88. }
  89. /// @brief Deletes all of the entries from the store.
  90. ///
  91. void clear() {
  92. values_.clear();
  93. }
  94. private:
  95. /// @brief An std::map of the data values, keyed by parameter names.
  96. std::map<std::string, ValueType> values_;
  97. };
  98. /// @brief a collection of elements that store uint32 values
  99. typedef ValueStorage<uint32_t> Uint32Storage;
  100. typedef boost::shared_ptr<Uint32Storage> Uint32StoragePtr;
  101. /// @brief a collection of elements that store string values
  102. typedef ValueStorage<std::string> StringStorage;
  103. typedef boost::shared_ptr<StringStorage> StringStoragePtr;
  104. /// @brief Storage for parsed boolean values.
  105. typedef ValueStorage<bool> BooleanStorage;
  106. typedef boost::shared_ptr<BooleanStorage> BooleanStoragePtr;
  107. /// @brief Container for the current parsing context. It provides a
  108. /// single enclosure for the storage of configuration parameters,
  109. /// options, option definitions, and other context specific information
  110. /// that needs to be accessible throughout the parsing and parsing
  111. /// constructs.
  112. class ParserContext {
  113. public:
  114. /// @brief Constructor
  115. ///
  116. /// @param universe is the Option::Universe value of this
  117. /// context.
  118. ParserContext(Option::Universe universe);
  119. /// @brief Copy constructor
  120. ParserContext(const ParserContext& rhs);
  121. /// @brief Storage for boolean parameters.
  122. BooleanStoragePtr boolean_values_;
  123. /// @brief Storage for uint32 parameters.
  124. Uint32StoragePtr uint32_values_;
  125. /// @brief Storage for string parameters.
  126. StringStoragePtr string_values_;
  127. /// @brief Storage for options.
  128. OptionStoragePtr options_;
  129. /// @brief Storage for option definitions.
  130. OptionDefStoragePtr option_defs_;
  131. /// @brief Hooks libraries pointer.
  132. ///
  133. /// The hooks libraries information is a vector of strings, each containing
  134. /// the name of a library. Hooks libraries should only be reloaded if the
  135. /// list of names has changed, so the list of current DHCP parameters
  136. /// (in isc::dhcp::CfgMgr) contains an indication as to whether the list has
  137. /// altered. This indication is implemented by storing a pointer to the
  138. /// list of library names which is cleared when the libraries are loaded.
  139. /// So either the pointer is null (meaning don't reload the libraries and
  140. /// the list of current names can be obtained from the HooksManager) or it
  141. /// is non-null (this is the new list of names, reload the libraries when
  142. /// possible).
  143. HooksLibsStoragePtr hooks_libraries_;
  144. /// @brief The parsing universe of this context.
  145. Option::Universe universe_;
  146. /// @brief Assignment operator
  147. ParserContext& operator=(const ParserContext& rhs);
  148. /// @brief Copy the context fields.
  149. ///
  150. /// This class method initializes the context data by copying the data
  151. /// stored in the context instance provided as an argument. Note that
  152. /// this function will also handle copying the NULL pointers.
  153. ///
  154. /// @param ctx context to be copied.
  155. void copyContext(const ParserContext& ctx);
  156. template<typename T>
  157. void copyContextPointer(const boost::shared_ptr<T>& source_ptr,
  158. boost::shared_ptr<T>& dest_ptr);
  159. };
  160. /// @brief Pointer to various parser context.
  161. typedef boost::shared_ptr<ParserContext> ParserContextPtr;
  162. /// @brief Simple data-type parser template class
  163. ///
  164. /// This is the template class for simple data-type parsers. It supports
  165. /// parsing a configuration parameter with specific data-type for its
  166. /// possible values. It provides a common constructor, commit, and templated
  167. /// data storage. The "build" method implementation must be provided by a
  168. /// declaring type.
  169. /// @param ValueType is the data type of the configuration paramater value
  170. /// the parser should handle.
  171. template<typename ValueType>
  172. class ValueParser : public DhcpConfigParser {
  173. public:
  174. /// @brief Constructor.
  175. ///
  176. /// @param param_name name of the parameter.
  177. /// @param storage is a pointer to the storage container where the parsed
  178. /// value be stored upon commit.
  179. /// @throw isc::dhcp::DhcpConfigError if a provided parameter's
  180. /// name is empty.
  181. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  182. ValueParser(const std::string& param_name,
  183. boost::shared_ptr<ValueStorage<ValueType> > storage)
  184. : storage_(storage), param_name_(param_name), value_() {
  185. // Empty parameter name is invalid.
  186. if (param_name_.empty()) {
  187. isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
  188. << "empty parameter name provided");
  189. }
  190. // NUll storage is invalid.
  191. if (!storage_) {
  192. isc_throw(isc::dhcp::DhcpConfigError, "parser logic error:"
  193. << "storage may not be NULL");
  194. }
  195. }
  196. /// @brief Parse a given element into a value of type @c ValueType
  197. ///
  198. /// @param value a value to be parsed.
  199. ///
  200. /// @throw isc::BadValue Typically the implementing type will throw
  201. /// a BadValue exception when given an invalid Element to parse.
  202. void build(isc::data::ConstElementPtr value);
  203. /// @brief Put a parsed value to the storage.
  204. void commit() {
  205. // If a given parameter already exists in the storage we override
  206. // its value. If it doesn't we insert a new element.
  207. storage_->setParam(param_name_, value_);
  208. }
  209. private:
  210. /// Pointer to the storage where committed value is stored.
  211. boost::shared_ptr<ValueStorage<ValueType> > storage_;
  212. /// Name of the parameter which value is parsed with this parser.
  213. std::string param_name_;
  214. /// Parsed value.
  215. ValueType value_;
  216. };
  217. /// @brief typedefs for simple data type parsers
  218. typedef ValueParser<bool> BooleanParser;
  219. typedef ValueParser<uint32_t> Uint32Parser;
  220. typedef ValueParser<std::string> StringParser;
  221. /// @brief a dummy configuration parser
  222. ///
  223. /// It is a debugging parser. It does not configure anything,
  224. /// will accept any configuration and will just print it out
  225. /// on commit. Useful for debugging existing configurations and
  226. /// adding new ones.
  227. class DebugParser : public DhcpConfigParser {
  228. public:
  229. /// @brief Constructor
  230. ///
  231. /// See @ref DhcpConfigParser class for details.
  232. ///
  233. /// @param param_name name of the parsed parameter
  234. DebugParser(const std::string& param_name);
  235. /// @brief builds parameter value
  236. ///
  237. /// See @ref DhcpConfigParser class for details.
  238. ///
  239. /// @param new_config pointer to the new configuration
  240. virtual void build(isc::data::ConstElementPtr new_config);
  241. /// @brief pretends to apply the configuration
  242. ///
  243. /// This is a method required by base class. It pretends to apply the
  244. /// configuration, but in fact it only prints the parameter out.
  245. ///
  246. /// See @ref DhcpConfigParser class for details.
  247. virtual void commit();
  248. private:
  249. /// name of the parsed parameter
  250. std::string param_name_;
  251. /// pointer to the actual value of the parameter
  252. isc::data::ConstElementPtr value_;
  253. };
  254. /// @brief parser for interface list definition
  255. ///
  256. /// This parser handles Dhcp4/interface entry.
  257. /// It contains a list of network interfaces that the server listens on.
  258. /// In particular, it can contain an entry called "all" or "any" that
  259. /// designates all interfaces.
  260. ///
  261. /// It is useful for parsing Dhcp4/interface parameter.
  262. class InterfaceListConfigParser : public DhcpConfigParser {
  263. public:
  264. /// @brief constructor
  265. ///
  266. /// As this is a dedicated parser, it must be used to parse
  267. /// "interface" parameter only. All other types will throw exception.
  268. ///
  269. /// @param param_name name of the configuration parameter being parsed
  270. /// @throw BadValue if supplied parameter name is not "interface"
  271. InterfaceListConfigParser(const std::string& param_name);
  272. /// @brief parses parameters value
  273. ///
  274. /// Parses configuration entry (list of parameters) and adds each element
  275. /// to the interfaces list.
  276. ///
  277. /// @param value pointer to the content of parsed values
  278. virtual void build(isc::data::ConstElementPtr value);
  279. /// @brief commits interfaces list configuration
  280. virtual void commit();
  281. private:
  282. /// @brief Check that specified interface exists in
  283. /// @c InterfaceListConfigParser::interfaces_.
  284. ///
  285. /// @param iface A name of the interface.
  286. ///
  287. /// @return true if specified interface name was found.
  288. bool isIfaceAdded(const std::string& iface) const;
  289. /// contains list of network interfaces
  290. typedef std::list<std::string> IfaceListStorage;
  291. IfaceListStorage interfaces_;
  292. // Should server listen on all interfaces.
  293. bool activate_all_;
  294. // Parsed parameter name
  295. std::string param_name_;
  296. };
  297. /// @brief Parser for hooks library list
  298. ///
  299. /// This parser handles the list of hooks libraries. This is an optional list,
  300. /// which may be empty.
  301. ///
  302. /// However, the parser does more than just check the list of library names.
  303. /// It does two other things:
  304. ///
  305. /// -# The problem faced with the hooks libraries is that we wish to avoid
  306. /// reloading the libraries if they have not changed. (This would cause the
  307. /// "unload" and "load" methods to run. Although libraries should be written
  308. /// to cope with this, it is feasible that such an action may be constly in
  309. /// terms of time and resources, or may cause side effects such as clearning
  310. /// an internal cache.) To this end, the parser also checks the list against
  311. /// the list of libraries current loaded and notes if there are changes.
  312. /// -# If there are, the parser validates the libraries; it opens them and
  313. /// checks that the "version" function exists and returns the correct value.
  314. ///
  315. /// Only if the library list has changed and the libraries are valid will the
  316. /// change be applied.
  317. class HooksLibrariesParser : public DhcpConfigParser {
  318. public:
  319. /// @brief Constructor
  320. ///
  321. /// As this is a dedicated parser, it must be used to parse
  322. /// "hooks-libraries" parameter only. All other types will throw exception.
  323. ///
  324. /// @param param_name name of the configuration parameter being parsed.
  325. ///
  326. /// @throw BadValue if supplied parameter name is not "hooks-libraries"
  327. HooksLibrariesParser(const std::string& param_name);
  328. /// @brief Parses parameters value
  329. ///
  330. /// Parses configuration entry (list of parameters) and adds each element
  331. /// to the hooks libraries list. The method also checks whether the
  332. /// list of libraries is the same as that already loaded. If not, it
  333. /// checks each of the libraries in the list for validity (they exist and
  334. /// have a "version" function that returns the correct value).
  335. ///
  336. /// @param value pointer to the content of parsed values
  337. virtual void build(isc::data::ConstElementPtr value);
  338. /// @brief Commits hooks libraries data
  339. ///
  340. /// Providing that the specified libraries are valid and are different
  341. /// to those already loaded, this method loads the new set of libraries
  342. /// (and unloads the existing set).
  343. virtual void commit();
  344. /// @brief Returns list of parsed libraries
  345. ///
  346. /// Principally for testing, this returns the list of libraries as well as
  347. /// an indication as to whether the list is different from the list of
  348. /// libraries already loaded.
  349. ///
  350. /// @param [out] libraries List of libraries that were specified in the
  351. /// new configuration.
  352. /// @param [out] changed true if the list is different from that currently
  353. /// loaded.
  354. void getLibraries(std::vector<std::string>& libraries, bool& changed);
  355. private:
  356. /// List of hooks libraries.
  357. std::vector<std::string> libraries_;
  358. /// Indicator flagging that the list of libraries has changed.
  359. bool changed_;
  360. };
  361. /// @brief Parser for option data value.
  362. ///
  363. /// This parser parses configuration entries that specify value of
  364. /// a single option. These entries include option name, option code
  365. /// and data carried by the option. The option data can be specified
  366. /// in one of the two available formats: binary value represented as
  367. /// a string of hexadecimal digits or a list of comma separated values.
  368. /// The format being used is controlled by csv-format configuration
  369. /// parameter. When setting this value to True, the latter format is
  370. /// used. The subsequent values in the CSV format apply to relevant
  371. /// option data fields in the configured option. For example the
  372. /// configuration: "data" : "192.168.2.0, 56, hello world" can be
  373. /// used to set values for the option comprising IPv4 address,
  374. /// integer and string data field. Note that order matters. If the
  375. /// order of values does not match the order of data fields within
  376. /// an option the configuration will not be accepted. If parsing
  377. /// is successful then an instance of an option is created and
  378. /// added to the storage provided by the calling class.
  379. class OptionDataParser : public DhcpConfigParser {
  380. public:
  381. /// @brief Constructor.
  382. ///
  383. /// @param dummy first argument is ignored, all Parser constructors
  384. /// accept string as first argument.
  385. /// @param options is the option storage in which to store the parsed option
  386. /// upon "commit".
  387. /// @param global_context is a pointer to the global context which
  388. /// stores global scope parameters, options, option defintions.
  389. /// @throw isc::dhcp::DhcpConfigError if options or global_context are null.
  390. OptionDataParser(const std::string& dummy, OptionStoragePtr options,
  391. ParserContextPtr global_context);
  392. /// @brief Parses the single option data.
  393. ///
  394. /// This method parses the data of a single option from the configuration.
  395. /// The option data includes option name, option code and data being
  396. /// carried by this option. Eventually it creates the instance of the
  397. /// option.
  398. ///
  399. /// @param option_data_entries collection of entries that define value
  400. /// for a particular option.
  401. /// @throw DhcpConfigError if invalid parameter specified in
  402. /// the configuration.
  403. /// @throw isc::InvalidOperation if failed to set storage prior to
  404. /// calling build.
  405. virtual void build(isc::data::ConstElementPtr option_data_entries);
  406. /// @brief Commits option value.
  407. ///
  408. /// This function adds a new option to the storage or replaces an existing
  409. /// option with the same code.
  410. ///
  411. /// @throw isc::InvalidOperation if failed to set pointer to storage or
  412. /// failed
  413. /// to call build() prior to commit. If that happens data in the storage
  414. /// remain un-modified.
  415. virtual void commit();
  416. /// @brief virtual destructor to ensure orderly destruction of derivations.
  417. virtual ~OptionDataParser(){};
  418. protected:
  419. /// @brief Finds an option definition within the server's option space
  420. ///
  421. /// Given an option space and an option code, find the correpsonding
  422. /// option defintion within the server's option defintion storage. This
  423. /// method is pure virtual requiring derivations to manage which option
  424. /// space(s) is valid for search.
  425. ///
  426. /// @param option_space name of the parameter option space
  427. /// @param option_code numeric value of the parameter to find
  428. /// @return OptionDefintionPtr of the option defintion or an
  429. /// empty OptionDefinitionPtr if not found.
  430. /// @throw DhcpConfigError if the option space requested is not valid
  431. /// for this server.
  432. virtual OptionDefinitionPtr findServerSpaceOptionDefinition (
  433. std::string& option_space, uint32_t option_code) = 0;
  434. private:
  435. /// @brief Create option instance.
  436. ///
  437. /// Creates an instance of an option and adds it to the provided
  438. /// options storage. If the option data parsed by \ref build function
  439. /// are invalid or insufficient this function emits an exception.
  440. ///
  441. /// @warning this function does not check if options_ storage pointer
  442. /// is intitialized but this check is not needed here because it is done
  443. /// in the \ref build function.
  444. ///
  445. /// @throw DhcpConfigError if parameters provided in the configuration
  446. /// are invalid.
  447. void createOption();
  448. /// Storage for boolean values.
  449. BooleanStoragePtr boolean_values_;
  450. /// Storage for string values (e.g. option name or data).
  451. StringStoragePtr string_values_;
  452. /// Storage for uint32 values (e.g. option code).
  453. Uint32StoragePtr uint32_values_;
  454. /// Pointer to options storage. This storage is provided by
  455. /// the calling class and is shared by all OptionDataParser objects.
  456. OptionStoragePtr options_;
  457. /// Option descriptor holds newly configured option.
  458. Subnet::OptionDescriptor option_descriptor_;
  459. /// Option space name where the option belongs to.
  460. std::string option_space_;
  461. /// Parsing context which contains global values, options and option
  462. /// definitions.
  463. ParserContextPtr global_context_;
  464. };
  465. ///@brief Function pointer for OptionDataParser factory methods
  466. typedef OptionDataParser *OptionDataParserFactory(const std::string&,
  467. OptionStoragePtr options, ParserContextPtr global_context);
  468. /// @brief Parser for option data values within a subnet.
  469. ///
  470. /// This parser iterates over all entries that define options
  471. /// data for a particular subnet and creates a collection of options.
  472. /// If parsing is successful, all these options are added to the Subnet
  473. /// object.
  474. class OptionDataListParser : public DhcpConfigParser {
  475. public:
  476. /// @brief Constructor.
  477. ///
  478. /// @param dummy nominally would be param name, this is always ignored.
  479. /// @param options parsed option storage for options in this list
  480. /// @param global_context is a pointer to the global context which
  481. /// stores global scope parameters, options, option defintions.
  482. /// @param optionDataParserFactory factory method for creating individual
  483. /// option parsers
  484. /// @throw isc::dhcp::DhcpConfigError if options or global_context are null.
  485. OptionDataListParser(const std::string& dummy, OptionStoragePtr options,
  486. ParserContextPtr global_context,
  487. OptionDataParserFactory *optionDataParserFactory);
  488. /// @brief Parses entries that define options' data for a subnet.
  489. ///
  490. /// This method iterates over all entries that define option data
  491. /// for options within a single subnet and creates options' instances.
  492. ///
  493. /// @param option_data_list pointer to a list of options' data sets.
  494. /// @throw DhcpConfigError if option parsing failed.
  495. void build(isc::data::ConstElementPtr option_data_list);
  496. /// @brief Commit all option values.
  497. ///
  498. /// This function invokes commit for all option values.
  499. void commit();
  500. private:
  501. /// Pointer to options instances storage.
  502. OptionStoragePtr options_;
  503. /// Intermediate option storage. This storage is used by
  504. /// lower level parsers to add new options. Values held
  505. /// in this storage are assigned to main storage (options_)
  506. /// if overall parsing was successful.
  507. OptionStoragePtr local_options_;
  508. /// Collection of parsers;
  509. ParserCollection parsers_;
  510. /// Parsing context which contains global values, options and option
  511. /// definitions.
  512. ParserContextPtr global_context_;
  513. /// Factory to create server-specific option data parsers
  514. OptionDataParserFactory *optionDataParserFactory_;
  515. };
  516. /// @brief Parser for a single option definition.
  517. ///
  518. /// This parser creates an instance of a single option definition.
  519. class OptionDefParser : public DhcpConfigParser {
  520. public:
  521. /// @brief Constructor.
  522. ///
  523. /// @param dummy first argument is ignored, all Parser constructors
  524. /// accept string as first argument.
  525. /// @param storage is the definition storage in which to store the parsed
  526. /// definition upon "commit".
  527. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  528. OptionDefParser(const std::string& dummy, OptionDefStoragePtr storage);
  529. /// @brief Parses an entry that describes single option definition.
  530. ///
  531. /// @param option_def a configuration entry to be parsed.
  532. ///
  533. /// @throw DhcpConfigError if parsing was unsuccessful.
  534. void build(isc::data::ConstElementPtr option_def);
  535. /// @brief Stores the parsed option definition in a storage.
  536. void commit();
  537. private:
  538. /// @brief Create option definition from the parsed parameters.
  539. void createOptionDef();
  540. /// Instance of option definition being created by this parser.
  541. OptionDefinitionPtr option_definition_;
  542. /// Name of the space the option definition belongs to.
  543. std::string option_space_name_;
  544. /// Pointer to a storage where the option definition will be
  545. /// added when \ref commit is called.
  546. OptionDefStoragePtr storage_;
  547. /// Storage for boolean values.
  548. BooleanStoragePtr boolean_values_;
  549. /// Storage for string values.
  550. StringStoragePtr string_values_;
  551. /// Storage for uint32 values.
  552. Uint32StoragePtr uint32_values_;
  553. };
  554. /// @brief Parser for a list of option definitions.
  555. ///
  556. /// This parser iterates over all configuration entries that define
  557. /// option definitions and creates instances of these definitions.
  558. /// If the parsing is successful, the collection of created definitions
  559. /// is put into the provided storage.
  560. class OptionDefListParser : public DhcpConfigParser {
  561. public:
  562. /// @brief Constructor.
  563. ///
  564. /// @param dummy first argument is ignored, all Parser constructors
  565. /// accept string as first argument.
  566. /// @param storage is the definition storage in which to store the parsed
  567. /// definitions in this list
  568. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  569. OptionDefListParser(const std::string& dummy, OptionDefStoragePtr storage);
  570. /// @brief Parse configuration entries.
  571. ///
  572. /// This function parses configuration entries and creates instances
  573. /// of option definitions.
  574. ///
  575. /// @param option_def_list pointer to an element that holds entries
  576. /// that define option definitions.
  577. /// @throw DhcpConfigError if configuration parsing fails.
  578. void build(isc::data::ConstElementPtr option_def_list);
  579. /// @brief Stores option definitions in the CfgMgr.
  580. void commit();
  581. private:
  582. /// @brief storage for option definitions.
  583. OptionDefStoragePtr storage_;
  584. };
  585. /// @brief a collection of pools
  586. ///
  587. /// That type is used as intermediate storage, when pools are parsed, but there is
  588. /// no subnet object created yet to store them.
  589. typedef std::vector<PoolPtr> PoolStorage;
  590. typedef boost::shared_ptr<PoolStorage> PoolStoragePtr;
  591. /// @brief parser for pool definition
  592. ///
  593. /// This abstract parser handles pool definitions, i.e. a list of entries of one
  594. /// of two syntaxes: min-max and prefix/len. Pool objects are created
  595. /// and stored in chosen PoolStorage container.
  596. ///
  597. /// It is useful for parsing Dhcp<4/6>/subnet<4/6>[X]/pool parameters.
  598. class PoolParser : public DhcpConfigParser {
  599. public:
  600. /// @brief constructor.
  601. ///
  602. /// @param dummy first argument is ignored, all Parser constructors
  603. /// accept string as first argument.
  604. /// @param pools is the storage in which to store the parsed pool
  605. /// upon "commit".
  606. /// @throw isc::dhcp::DhcpConfigError if storage is null.
  607. PoolParser(const std::string& dummy, PoolStoragePtr pools);
  608. /// @brief parses the actual list
  609. ///
  610. /// This method parses the actual list of interfaces.
  611. /// No validation is done at this stage, everything is interpreted as
  612. /// interface name.
  613. /// @param pools_list list of pools defined for a subnet
  614. /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
  615. virtual void build(isc::data::ConstElementPtr pools_list);
  616. /// @brief Stores the parsed values in a storage provided
  617. /// by an upper level parser.
  618. virtual void commit();
  619. protected:
  620. /// @brief Creates a Pool object given a IPv4 prefix and the prefix length.
  621. ///
  622. /// @param addr is the IP prefix of the pool.
  623. /// @param len is the prefix length.
  624. /// @param ptype is the type of pool to create.
  625. /// @return returns a PoolPtr to the new Pool object.
  626. virtual PoolPtr poolMaker(isc::asiolink::IOAddress &addr, uint32_t len,
  627. int32_t ptype=0) = 0;
  628. /// @brief Creates a Pool object given starting and ending IP addresses.
  629. ///
  630. /// @param min is the first IP address in the pool.
  631. /// @param max is the last IP address in the pool.
  632. /// @param ptype is the type of pool to create (not used by all derivations)
  633. /// @return returns a PoolPtr to the new Pool object.
  634. virtual PoolPtr poolMaker(isc::asiolink::IOAddress &min,
  635. isc::asiolink::IOAddress &max, int32_t ptype=0) = 0;
  636. /// @brief pointer to the actual Pools storage
  637. ///
  638. /// That is typically a storage somewhere in Subnet parser
  639. /// (an upper level parser).
  640. PoolStoragePtr pools_;
  641. /// A temporary storage for pools configuration. It is a
  642. /// storage where pools are stored by build function.
  643. PoolStorage local_pools_;
  644. };
  645. /// @brief this class parses a single subnet
  646. ///
  647. /// This class parses the whole subnet definition. It creates parsers
  648. /// for received configuration parameters as needed.
  649. class SubnetConfigParser : public DhcpConfigParser {
  650. public:
  651. /// @brief constructor
  652. SubnetConfigParser(const std::string&, ParserContextPtr global_context);
  653. /// @brief parses parameter value
  654. ///
  655. /// @param subnet pointer to the content of subnet definition
  656. ///
  657. /// @throw isc::DhcpConfigError if subnet configuration parsing failed.
  658. virtual void build(isc::data::ConstElementPtr subnet);
  659. /// @brief Adds the created subnet to a server's configuration.
  660. virtual void commit() = 0;
  661. /// @brief tries to convert option_space string to numeric vendor_id
  662. ///
  663. /// This will work if the option_space has format "vendor-X", where
  664. /// X can be any value between 1 and MAX_UINT32.
  665. /// This is used to detect whether a given option-space is a vendor
  666. /// space or not. Returns 0 if the format is different.
  667. /// @return numeric vendor-id (or 0 if the format does not match)
  668. static uint32_t optionSpaceToVendorId(const std::string& option_space);
  669. protected:
  670. /// @brief creates parsers for entries in subnet definition
  671. ///
  672. /// @param config_id name od the entry
  673. ///
  674. /// @return parser object for specified entry name
  675. /// @throw isc::dhcp::DhcpConfigError if trying to create a parser
  676. /// for unknown config element
  677. virtual DhcpConfigParser* createSubnetConfigParser(
  678. const std::string& config_id) = 0;
  679. /// @brief Determines if the given option space name and code describe
  680. /// a standard option for the server.
  681. ///
  682. /// @param option_space is the name of the option space to consider
  683. /// @param code is the numeric option code to consider
  684. /// @return returns true if the space and code are part of the server's
  685. /// standard options.
  686. virtual bool isServerStdOption(std::string option_space, uint32_t code) = 0;
  687. /// @brief Returns the option definition for a given option code from
  688. /// the server's standard set of options.
  689. /// @param code is the numeric option code of the desired option definition.
  690. /// @return returns a pointer the option definition
  691. virtual OptionDefinitionPtr getServerStdOptionDefinition (
  692. uint32_t code) = 0;
  693. /// @brief Issues a server specific warning regarding duplicate subnet
  694. /// options.
  695. ///
  696. /// @param code is the numeric option code of the duplicate option
  697. /// @param addr is the subnet address
  698. /// @todo a means to know the correct logger and perhaps a common
  699. /// message would allow this method to be emitted by the base class.
  700. virtual void duplicate_option_warning(uint32_t code,
  701. isc::asiolink::IOAddress& addr) = 0;
  702. /// @brief Instantiates the subnet based on a given IP prefix and prefix
  703. /// length.
  704. ///
  705. /// @param addr is the IP prefix of the subnet.
  706. /// @param len is the prefix length
  707. virtual void initSubnet(isc::asiolink::IOAddress addr, uint8_t len) = 0;
  708. /// @brief Returns value for a given parameter (after using inheritance)
  709. ///
  710. /// This method implements inheritance. For a given parameter name, it first
  711. /// checks if there is a global value for it and overwrites it with specific
  712. /// value if such value was defined in subnet.
  713. ///
  714. /// @param name name of the parameter
  715. /// @return triplet with the parameter name
  716. /// @throw DhcpConfigError when requested parameter is not present
  717. isc::dhcp::Triplet<uint32_t> getParam(const std::string& name);
  718. private:
  719. /// @brief Append sub-options to an option.
  720. ///
  721. /// @param option_space a name of the encapsulated option space.
  722. /// @param option option instance to append sub-options to.
  723. void appendSubOptions(const std::string& option_space, OptionPtr& option);
  724. /// @brief Create a new subnet using a data from child parsers.
  725. ///
  726. /// @throw isc::dhcp::DhcpConfigError if subnet configuration parsing
  727. /// failed.
  728. void createSubnet();
  729. protected:
  730. /// Storage for subnet-specific integer values.
  731. Uint32StoragePtr uint32_values_;
  732. /// Storage for subnet-specific string values.
  733. StringStoragePtr string_values_;
  734. /// Storage for pools belonging to this subnet.
  735. PoolStoragePtr pools_;
  736. /// Storage for options belonging to this subnet.
  737. OptionStoragePtr options_;
  738. /// Parsers are stored here.
  739. ParserCollection parsers_;
  740. /// Pointer to the created subnet object.
  741. isc::dhcp::SubnetPtr subnet_;
  742. /// Parsing context which contains global values, options and option
  743. /// definitions.
  744. ParserContextPtr global_context_;
  745. };
  746. /// @brief Parser for D2ClientConfig
  747. ///
  748. /// This class parses the configuration element "dhcp-ddns" common to the
  749. /// spec files for both dhcp4 and dhcp6. It creates an instance of a
  750. /// D2ClientConfig.
  751. class D2ClientConfigParser : public isc::dhcp::DhcpConfigParser {
  752. public:
  753. /// @brief Constructor
  754. ///
  755. /// @param entry_name is an arbitrary label assigned to this configuration
  756. /// definition.
  757. D2ClientConfigParser(const std::string& entry_name);
  758. /// @brief Destructor
  759. virtual ~D2ClientConfigParser();
  760. /// @brief Performs the parsing of the given dhcp-ddns element.
  761. ///
  762. /// The results of the parsing are retained internally for use during
  763. /// commit.
  764. ///
  765. /// @param client_config is the "dhcp-ddns" configuration to parse
  766. virtual void build(isc::data::ConstElementPtr client_config);
  767. /// @brief Creates a parser for the given "dhcp-ddns" member element id.
  768. ///
  769. /// The elements currently supported are (see isc::dhcp::D2ClientConfig
  770. /// for details on each):
  771. /// -# enable-updates
  772. /// -# server-ip
  773. /// -# server-port
  774. /// -# ncr-protocol
  775. /// -# ncr-format
  776. /// -# remove-on-renew
  777. /// -# always-include-fqdn
  778. /// -# allow-client-update
  779. /// -# override-no-update
  780. /// -# override-client-update
  781. /// -# replace-client-name
  782. /// -# generated-prefix
  783. /// -# qualifying-suffix
  784. ///
  785. /// @param config_id is the "item_name" for a specific member element of
  786. /// the "dns_server" specification.
  787. ///
  788. /// @return returns a pointer to newly created parser.
  789. virtual isc::dhcp::ParserPtr createConfigParser(const std::string&
  790. config_id);
  791. /// @brief Instantiates a D2ClientConfig from internal data values
  792. /// passes to CfgMgr singleton.
  793. virtual void commit();
  794. private:
  795. /// @brief Arbitrary label assigned to this parser instance.
  796. /// Primarily used for diagnostics.
  797. std::string entry_name_;
  798. /// Storage for subnet-specific boolean values.
  799. BooleanStoragePtr boolean_values_;
  800. /// Storage for subnet-specific integer values.
  801. Uint32StoragePtr uint32_values_;
  802. /// Storage for subnet-specific string values.
  803. StringStoragePtr string_values_;
  804. /// @brief Pointer to temporary local instance created during build.
  805. D2ClientConfigPtr local_client_config_ ;
  806. };
  807. // Pointers to various parser objects.
  808. typedef boost::shared_ptr<BooleanParser> BooleanParserPtr;
  809. typedef boost::shared_ptr<StringParser> StringParserPtr;
  810. typedef boost::shared_ptr<Uint32Parser> Uint32ParserPtr;
  811. }; // end of isc::dhcp namespace
  812. }; // end of isc namespace
  813. #endif // DHCP_PARSERS_H