dhcp_parsers.h 41 KB

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