option_definition.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. // Copyright (C) 2012-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 OPTION_DEFINITION_H
  15. #define OPTION_DEFINITION_H
  16. #include <dhcp/option.h>
  17. #include <dhcp/option_data_types.h>
  18. #include <boost/multi_index/hashed_index.hpp>
  19. #include <boost/multi_index/mem_fun.hpp>
  20. #include <boost/multi_index/sequenced_index.hpp>
  21. #include <boost/multi_index_container.hpp>
  22. #include <boost/shared_ptr.hpp>
  23. #include <map>
  24. namespace isc {
  25. namespace dhcp {
  26. /// @brief Exception to be thrown when invalid option value has been
  27. /// specified for a particular option definition.
  28. class InvalidOptionValue : public Exception {
  29. public:
  30. InvalidOptionValue(const char* file, size_t line, const char* what) :
  31. isc::Exception(file, line, what) { };
  32. };
  33. /// @brief Exception to be thrown when option definition is invalid.
  34. class MalformedOptionDefinition : public Exception {
  35. public:
  36. MalformedOptionDefinition(const char* file, size_t line, const char* what) :
  37. isc::Exception(file, line, what) { };
  38. };
  39. /// @brief Exception to be thrown when the particular option definition
  40. /// duplicates existing option definition.
  41. class DuplicateOptionDefinition : public Exception {
  42. public:
  43. DuplicateOptionDefinition(const char* file, size_t line, const char* what) :
  44. isc::Exception(file, line, what) { };
  45. };
  46. /// @brief Forward declaration to OptionDefinition.
  47. class OptionDefinition;
  48. /// @brief Pointer to option definition object.
  49. typedef boost::shared_ptr<OptionDefinition> OptionDefinitionPtr;
  50. /// @brief Forward declaration to OptionInt.
  51. ///
  52. /// This forward declaration is needed to access the OptionInt class without
  53. /// having to include the option_int.h header file. It is required because
  54. /// this header includes libdhcp++.h, and including option_int.h would cause
  55. /// circular inclusion between libdhcp++.h, option_definition.h and
  56. /// option6_int.h.
  57. template<typename T>
  58. class OptionInt;
  59. /// @brief Forward declaration to OptionIntArray.
  60. ///
  61. /// This forward declaration is needed to access the OptionIntArray class
  62. /// without having to include the option_int_array.h header file. It is
  63. /// required because this header includes libdhcp++.h, and including
  64. /// option_int_array.h would cause circular inclusion between libdhcp++.h,
  65. /// option_definition.h and option_int_array.h.
  66. template<typename T>
  67. class OptionIntArray;
  68. /// @brief Base class representing a DHCP option definition.
  69. ///
  70. /// This is a base class representing a DHCP option definition, which describes
  71. /// the format of the option. In particular, it defines:
  72. /// - option name,
  73. /// - option code,
  74. /// - data fields order and their types,
  75. /// - sub options space that the particular option encapsulates.
  76. ///
  77. /// The option type specifies the data type(s) which an option conveys. If
  78. /// this is a single value the option type points to the data type of the
  79. /// value. For example, DHCPv6 option 8 comprises a two-byte option code, a
  80. /// two-byte option length and two-byte field that carries a uint16 value
  81. /// (RFC 3315 - http://ietf.org/rfc/rfc3315.txt). In such a case, the option
  82. /// type is defined as "uint16".
  83. ///
  84. /// When the option has a more complex structure, the option type may be
  85. /// defined as "array", "record" or even "array of records".
  86. ///
  87. /// Array types should be used when the option contains multiple contiguous
  88. /// data values of the same type laid. For example, DHCPv6 option 6 includes
  89. /// multiple fields holding uint16 codes of requested DHCPv6 options (RFC 3315).
  90. /// Such an option can be represented with this class by setting the option
  91. /// type to "uint16" and the array indicator (array_type) to true. The number
  92. /// of elements in the array is effectively unlimited (although it is actually
  93. /// limited by the maximal DHCPv6 option length).
  94. ///
  95. /// Should the option comprise data fields of different types, the "record"
  96. /// option type is used. In such cases the data field types within the record
  97. /// are specified using \ref OptionDefinition::addRecordField.
  98. ///
  99. /// When the OptionDefinition object has been sucessfully created, it can be
  100. /// queried to return the appropriate option factory function for the specified
  101. /// specified option format. There are a number of "standard" factory functions
  102. /// that cover well known (common) formats. If the particular format does not
  103. /// match any common format the generic factory function is returned.
  104. ///
  105. /// The following data type strings are supported:
  106. /// - "empty" (option does not contain data fields)
  107. /// - "boolean"
  108. /// - "int8"
  109. /// - "int16"
  110. /// - "int32"
  111. /// - "uint8"
  112. /// - "uint16"
  113. /// - "uint32"
  114. /// - "ipv4-address" (IPv4 Address)
  115. /// - "ipv6-address" (IPV6 Address)
  116. /// - "string"
  117. /// - "fqdn" (fully qualified name)
  118. /// - "record" (set of data fields of different types)
  119. ///
  120. /// @todo Extend the comment to describe "generic factories".
  121. /// @todo Extend this class to use custom namespaces.
  122. /// @todo Extend this class with more factory functions.
  123. class OptionDefinition {
  124. public:
  125. /// List of fields within the record.
  126. typedef std::vector<OptionDataType> RecordFieldsCollection;
  127. /// Const iterator for record data fields.
  128. typedef std::vector<OptionDataType>::const_iterator RecordFieldsConstIter;
  129. /// @brief Constructor.
  130. ///
  131. /// @param name option name.
  132. /// @param code option code.
  133. /// @param type option data type as string.
  134. /// @param array_type array indicator, if true it indicates that the
  135. /// option fields are the array.
  136. explicit OptionDefinition(const std::string& name,
  137. const uint16_t code,
  138. const std::string& type,
  139. const bool array_type = false);
  140. /// @brief Constructor.
  141. ///
  142. /// @param name option name.
  143. /// @param code option code.
  144. /// @param type option data type.
  145. /// @param array_type array indicator, if true it indicates that the
  146. /// option fields are the array.
  147. explicit OptionDefinition(const std::string& name,
  148. const uint16_t code,
  149. const OptionDataType type,
  150. const bool array_type = false);
  151. /// @brief Constructor.
  152. ///
  153. /// This constructor sets the name of the option space that is
  154. /// encapsulated by this option. The encapsulated option space
  155. /// identifies sub-options that are carried within this option.
  156. /// This constructor does not allow to set array indicator
  157. /// because options comprising an array of data fields must
  158. /// not be used with sub-options.
  159. ///
  160. /// @param name option name.
  161. /// @param code option code.
  162. /// @param type option data type given as string.
  163. /// @param encapsulated_space name of the option space being
  164. /// encapsulated by this option.
  165. explicit OptionDefinition(const std::string& name,
  166. const uint16_t code,
  167. const std::string& type,
  168. const char* encapsulated_space);
  169. /// @brief Constructor.
  170. ///
  171. /// This constructor sets the name of the option space that is
  172. /// encapsulated by this option. The encapsulated option space
  173. /// identifies sub-options that are carried within this option.
  174. /// This constructor does not allow to set array indicator
  175. /// because options comprising an array of data fields must
  176. /// not be used with sub-options.
  177. ///
  178. /// @param name option name.
  179. /// @param code option code.
  180. /// @param type option data type.
  181. /// @param encapsulated_space name of the option space being
  182. /// encapsulated by this option.
  183. explicit OptionDefinition(const std::string& name,
  184. const uint16_t code,
  185. const OptionDataType type,
  186. const char* encapsulated_space);
  187. /// @name Comparison functions and operators.
  188. ///
  189. //@{
  190. /// @brief Check if option definition is equal to other.
  191. ///
  192. /// @param other Option definition to compare to.
  193. ///
  194. /// @return true if two option definitions are equal, false otherwise.
  195. bool equals(const OptionDefinition& other) const;
  196. /// @brief Equality operator.
  197. ///
  198. /// @param other Option definition to compare to.
  199. ///
  200. /// @return true if two option definitions are equal, false otherwise.
  201. bool operator==(const OptionDefinition& other) const {
  202. return (equals(other));
  203. }
  204. /// @brief Inequality operator.
  205. ///
  206. /// @param other Option definition to compare to.
  207. ///
  208. /// @return true if option definitions are not equal, false otherwise.
  209. bool operator!=(const OptionDefinition& other) const {
  210. return (!equals(other));
  211. }
  212. //@}
  213. /// @brief Adds data field to the record.
  214. ///
  215. /// @param data_type_name name of the data type for the field.
  216. ///
  217. /// @throw isc::InvalidOperation if option type is not set to RECORD_TYPE.
  218. /// @throw isc::BadValue if specified invalid data type.
  219. void addRecordField(const std::string& data_type_name);
  220. /// @brief Adds data field to the record.
  221. ///
  222. /// @param data_type data type for the field.
  223. ///
  224. /// @throw isc::InvalidOperation if option type is not set to RECORD_TYPE.
  225. /// @throw isc::BadValue if specified invalid data type.
  226. void addRecordField(const OptionDataType data_type);
  227. /// @brief Return array type indicator.
  228. ///
  229. /// The method returns the bool value to indicate whether the option is a
  230. /// a single value or an array of values.
  231. ///
  232. /// @return true if option comprises an array of values.
  233. bool getArrayType() const { return (array_type_); }
  234. /// @brief Return option code.
  235. ///
  236. /// @return option code.
  237. uint16_t getCode() const { return (code_); }
  238. /// @brief Return name of the encapsulated option space.
  239. ///
  240. /// @return name of the encapsulated option space.
  241. std::string getEncapsulatedSpace() const {
  242. return (encapsulated_space_);
  243. }
  244. /// @brief Return option name.
  245. ///
  246. /// @return option name.
  247. std::string getName() const { return (name_); }
  248. /// @brief Return list of record fields.
  249. ///
  250. /// @return list of record fields.
  251. const RecordFieldsCollection& getRecordFields() const {
  252. return (record_fields_);
  253. }
  254. /// @brief Return option data type.
  255. ///
  256. /// @return option data type.
  257. OptionDataType getType() const { return (type_); };
  258. /// @brief Check if the option definition is valid.
  259. ///
  260. /// Note that it is a responsibility of the code that created
  261. /// the OptionDefinition object to validate that it is valid.
  262. /// This function will not be called internally anywhere in this
  263. /// class to verify that the option definition is valid. Using
  264. /// invalid option definition to create an instance of the
  265. /// DHCP option leads to undefined behavior.
  266. ///
  267. /// @throw MalformedOptionDefinition option definition is invalid.
  268. void validate() const;
  269. /// @brief Check if specified format is IA_NA option format.
  270. ///
  271. /// @return true if specified format is IA_NA option format.
  272. bool haveIA6Format() const;
  273. /// @brief Check if specified format is IAADDR option format.
  274. ///
  275. /// @return true if specified format is IAADDR option format.
  276. bool haveIAAddr6Format() const;
  277. /// @brief Check if specified format is IAPREFIX option format.
  278. ///
  279. /// @return true if specified format is IAPREFIX option format.
  280. bool haveIAPrefix6Format() const;
  281. /// @brief Check if specified format is OPTION_CLIENT_FQDN option format.
  282. ///
  283. /// @return true of specified format is OPTION_CLIENT_FQDN option format,
  284. /// false otherwise.
  285. bool haveClientFqdnFormat() const;
  286. /// @brief Check if option has format of the DHCPv4 Client FQDN
  287. /// %Option.
  288. ///
  289. /// The encoding of the domain-name carried by the FQDN option is
  290. /// conditional and is specified in the flags field of the option.
  291. /// The domain-name can be encoded in the ASCII format or canonical
  292. /// wire format. The ASCII format is deprecated, therefore canonical
  293. /// format is selected for the FQDN option definition and this function
  294. /// returns true if the option definition comprises the domain-name
  295. /// field encoded in canonical format.
  296. ///
  297. /// @return true if option has the format of DHCPv4 Client FQDN
  298. /// %Option.
  299. bool haveFqdn4Format() const;
  300. /// @brief Check if the option has format of Vendor-Identifying Vendor
  301. /// Specific Options.
  302. ///
  303. /// @return Always true.
  304. /// @todo The Vendor-Identifying Vendor-Specific Option has a complex format
  305. /// which we do not support here. Therefore it is not really possible to
  306. /// check that the current definition is valid. We may need to add support
  307. /// for such option format or simply do not check the format for certain
  308. /// options, e.g. vendor options, IA_NA, IAADDR and always return objects
  309. /// of the certain type.
  310. bool haveVendor4Format() const;
  311. /// @brief Check if option has a format of the Vendor-Specific Information
  312. /// %Option.
  313. ///
  314. /// The Vendor-Specific Information %Option comprises 32-bit enterprise id
  315. /// and the suboptions.
  316. ///
  317. /// @return true if option definition conforms to the format of the
  318. /// Vendor-Specific Information %Option.
  319. bool haveVendor6Format() const;
  320. /// @brief Check if the option has format of DHCPv4 V-I Vendor Class option.
  321. ///
  322. /// @return true if the option has the format of DHCPv4 Vendor Class option.
  323. bool haveVendorClass4Format() const;
  324. /// @brief Check if the option has format of DHCPv6 Vendor Class option.
  325. ///
  326. /// @return true if option has the format of DHCPv6 Vendor Class option.
  327. bool haveVendorClass6Format() const;
  328. /// @brief Option factory.
  329. ///
  330. /// This function creates an instance of DHCP option using
  331. /// provided chunk of buffer. This function may be used to
  332. /// create option which is to be sent in the outgoing packet.
  333. ///
  334. /// @warning calling this function on invalid option definition
  335. /// yields undefined behavior. Use \ref validate to test that
  336. /// the option definition is valid.
  337. ///
  338. /// @param u option universe (V4 or V6).
  339. /// @param type option type.
  340. /// @param begin beginning of the option buffer.
  341. /// @param end end of the option buffer.
  342. /// @param callback An instance of the function which parses packet options.
  343. /// If this is set to non NULL value this function will be used instead of
  344. /// @c isc::dhcp::LibDHCP::unpackOptions6 and
  345. /// isc::dhcp::LibDHCP::unpackOptions4.
  346. ///
  347. /// @return instance of the DHCP option.
  348. /// @throw InvalidOptionValue if data for the option is invalid.
  349. OptionPtr optionFactory(Option::Universe u, uint16_t type,
  350. OptionBufferConstIter begin,
  351. OptionBufferConstIter end,
  352. UnpackOptionsCallback callback = NULL) const;
  353. /// @brief Option factory.
  354. ///
  355. /// This function creates an instance of DHCP option using
  356. /// whole provided buffer. This function may be used to
  357. /// create option which is to be sent in the outgoing packet.
  358. ///
  359. /// @warning calling this function on invalid option definition
  360. /// yields undefined behavior. Use \ref validate to test that
  361. /// the option definition is valid.
  362. ///
  363. /// @param u option universe (V4 or V6).
  364. /// @param type option type.
  365. /// @param buf option buffer.
  366. /// @param callback An instance of the function which parses packet options.
  367. /// If this is set to non NULL value this function will be used instead of
  368. /// @c isc::dhcp::LibDHCP::unpackOptions6 and
  369. /// isc::dhcp::LibDHCP::unpackOptions4.
  370. ///
  371. /// @return instance of the DHCP option.
  372. /// @throw InvalidOptionValue if data for the option is invalid.
  373. OptionPtr optionFactory(Option::Universe u, uint16_t type,
  374. const OptionBuffer& buf = OptionBuffer(),
  375. UnpackOptionsCallback callback = NULL) const;
  376. /// @brief Option factory.
  377. ///
  378. /// This function creates an instance of DHCP option using the vector
  379. /// of strings which carry data values for option data fields.
  380. /// The order of values in the vector corresponds to the order of data
  381. /// fields in the option. The supplied string values are cast to
  382. /// their actual data types which are determined based on the
  383. /// option definition. If cast fails due to type mismatch, an exception
  384. /// is thrown. This factory function can be used to create option
  385. /// instance when user specified option value in the <b>comma separated
  386. /// values</b> format in the configuration database. Provided string
  387. /// must be tokenized into the vector of string values and this vector
  388. /// can be supplied to this function.
  389. ///
  390. /// @warning calling this function on invalid option definition
  391. /// yields undefined behavior. Use \ref validate to test that
  392. /// the option definition is valid.
  393. ///
  394. /// @param u option universe (V4 or V6).
  395. /// @param type option type.
  396. /// @param values a vector of values to be used to set data for an option.
  397. ///
  398. /// @return instance of the DHCP option.
  399. /// @throw InvalidOptionValue if data for the option is invalid.
  400. OptionPtr optionFactory(Option::Universe u, uint16_t type,
  401. const std::vector<std::string>& values) const;
  402. /// @brief Factory to create option with address list.
  403. ///
  404. /// @param type option type.
  405. /// @param begin iterator pointing to the beginning of the buffer
  406. /// with a list of IPv4 addresses.
  407. /// @param end iterator pointing to the end of the buffer with
  408. /// a list of IPv4 addresses.
  409. ///
  410. /// @throw isc::OutOfRange if length of the provided option buffer
  411. /// is not multiple of IPV4 address length.
  412. static OptionPtr factoryAddrList4(uint16_t type,
  413. OptionBufferConstIter begin,
  414. OptionBufferConstIter end);
  415. /// @brief Factory to create option with address list.
  416. ///
  417. /// @param type option type.
  418. /// @param begin iterator pointing to the beginning of the buffer
  419. /// with a list of IPv6 addresses.
  420. /// @param end iterator pointing to the end of the buffer with
  421. /// a list of IPv6 addresses.
  422. ///
  423. /// @throw isc::OutOfaRange if length of provided option buffer
  424. /// is not multiple of IPV6 address length.
  425. static OptionPtr factoryAddrList6(uint16_t type,
  426. OptionBufferConstIter begin,
  427. OptionBufferConstIter end);
  428. /// @brief Empty option factory.
  429. ///
  430. /// @param u universe (V6 or V4).
  431. /// @param type option type.
  432. static OptionPtr factoryEmpty(Option::Universe u, uint16_t type);
  433. /// @brief Factory to create generic option.
  434. ///
  435. /// @param u universe (V6 or V4).
  436. /// @param type option type.
  437. /// @param begin iterator pointing to the beginning of the buffer.
  438. /// @param end iterator pointing to the end of the buffer.
  439. static OptionPtr factoryGeneric(Option::Universe u, uint16_t type,
  440. OptionBufferConstIter begin,
  441. OptionBufferConstIter end);
  442. /// @brief Factory for IA-type of option.
  443. ///
  444. /// @param type option type.
  445. /// @param begin iterator pointing to the beginning of the buffer.
  446. /// @param end iterator pointing to the end of the buffer.
  447. ///
  448. /// @throw isc::OutOfRange if provided option buffer is too short or
  449. /// too long. Expected size is 12 bytes.
  450. static OptionPtr factoryIA6(uint16_t type,
  451. OptionBufferConstIter begin,
  452. OptionBufferConstIter end);
  453. /// @brief Factory for IAADDR-type of option.
  454. ///
  455. /// @param type option type.
  456. /// @param begin iterator pointing to the beginning of the buffer.
  457. /// @param end iterator pointing to the end of the buffer.
  458. ///
  459. /// @throw isc::OutOfRange if provided option buffer is too short or
  460. /// too long. Expected size is 24 bytes.
  461. static OptionPtr factoryIAAddr6(uint16_t type,
  462. OptionBufferConstIter begin,
  463. OptionBufferConstIter end);
  464. /// @brief Factory for IAPREFIX-type of option.
  465. ///
  466. /// @param type option type.
  467. /// @param begin iterator pointing to the beginning of the buffer.
  468. /// @param end iterator pointing to the end of the buffer.
  469. ///
  470. /// @throw isc::OutOfRange if provided option buffer is too short.
  471. /// Expected minimum size is 25 bytes.
  472. static OptionPtr factoryIAPrefix6(uint16_t type,
  473. OptionBufferConstIter begin,
  474. OptionBufferConstIter end);
  475. /// @brief Factory function to create option with integer value.
  476. ///
  477. /// @param u universe (V4 or V6).
  478. /// @param type option type.
  479. /// @param encapsulated_space An option space being encapsulated by the
  480. /// options created by this factory function. The options which belong to
  481. /// encapsulated option space are sub options of this option.
  482. /// @param begin iterator pointing to the beginning of the buffer.
  483. /// @param end iterator pointing to the end of the buffer.
  484. /// @param callback An instance of the function which parses packet options.
  485. /// If this is set to non NULL value this function will be used instead of
  486. /// @c isc::dhcp::LibDHCP::unpackOptions6 and
  487. /// isc::dhcp::LibDHCP::unpackOptions4.
  488. /// @tparam T type of the data field (must be one of the uintX_t or intX_t).
  489. ///
  490. /// @throw isc::OutOfRange if provided option buffer length is invalid.
  491. template<typename T>
  492. static OptionPtr factoryInteger(Option::Universe u, uint16_t type,
  493. const std::string& encapsulated_space,
  494. OptionBufferConstIter begin,
  495. OptionBufferConstIter end,
  496. UnpackOptionsCallback callback) {
  497. OptionPtr option(new OptionInt<T>(u, type, 0));
  498. option->setEncapsulatedSpace(encapsulated_space);
  499. option->setCallback(callback);
  500. option->unpack(begin, end);
  501. return (option);
  502. }
  503. /// @brief Factory function to create option with array of integer values.
  504. ///
  505. /// @param u universe (V4 or V6).
  506. /// @param type option type.
  507. /// @param begin iterator pointing to the beginning of the buffer.
  508. /// @param end iterator pointing to the end of the buffer.
  509. /// @tparam T type of the data field (must be one of the uintX_t or intX_t).
  510. ///
  511. /// @throw isc::OutOfRange if provided option buffer length is invalid.
  512. template<typename T>
  513. static OptionPtr factoryIntegerArray(Option::Universe u,
  514. uint16_t type,
  515. OptionBufferConstIter begin,
  516. OptionBufferConstIter end) {
  517. OptionPtr option(new OptionIntArray<T>(u, type, begin, end));
  518. return (option);
  519. }
  520. private:
  521. /// @brief Creates an instance of an option having special format.
  522. ///
  523. /// The option with special formats are encapsulated by the dedicated
  524. /// classes derived from @c Option class. In particular these are:
  525. /// - IA_NA
  526. /// - IAADDR
  527. /// - FQDN
  528. /// - VIVSO.
  529. ///
  530. /// @param u A universe (V4 or V6).
  531. /// @param begin beginning of the option buffer.
  532. /// @param end end of the option buffer.
  533. /// @param callback An instance of the function which parses packet options.
  534. /// If this is set to non NULL value this function will be used instead of
  535. /// @c isc::dhcp::LibDHCP::unpackOptions6 and
  536. /// isc::dhcp::LibDHCP::unpackOptions4.
  537. ///
  538. /// @return An instance of the option having special format or NULL if
  539. /// such an option can't be created because an option with the given
  540. /// option code hasn't got the special format.
  541. OptionPtr factorySpecialFormatOption(Option::Universe u,
  542. OptionBufferConstIter begin,
  543. OptionBufferConstIter end,
  544. UnpackOptionsCallback callback) const;
  545. /// @brief Check if specified option format is a record with 3 fields
  546. /// where first one is custom, and two others are uint32.
  547. ///
  548. /// This is a helper function for functions that detect IA_NA and IAAddr
  549. /// option formats.
  550. ///
  551. /// @param first_type type of the first data field.
  552. ///
  553. /// @return true if actual option format matches expected format.
  554. bool haveIAx6Format(const OptionDataType first_type) const;
  555. /// @brief Check if specified type matches option definition type.
  556. ///
  557. /// @return true if specified type matches option definition type.
  558. inline bool haveType(const OptionDataType type) const {
  559. return (type == type_);
  560. }
  561. /// @brief Converts a string value to a boolean value.
  562. ///
  563. /// This function converts the value represented as string to a boolean
  564. /// value. The following conversions are acceptable:
  565. /// - "true" => true
  566. /// - "false" => false
  567. /// - "1" => true
  568. /// - "0" => false
  569. /// The first two conversions are case insensitive, so as conversions from
  570. /// strings such as "TRUE", "trUE" etc. will be accepted. Note that the
  571. /// only acceptable integer values, carried as strings are: "0" and "1".
  572. /// For other values, e.g. "2", "3" etc. an exception will be thrown
  573. /// during conversion.
  574. ///
  575. /// @param value_str Input value.
  576. ///
  577. /// @return boolean representation of the string specified as the parameter.
  578. /// @throw isc::dhcp::BadDataTypeCast if failed to perform the conversion.
  579. bool convertToBool(const std::string& value_str) const;
  580. /// @brief Perform lexical cast of the value and validate its range.
  581. ///
  582. /// This function performs lexical cast of a string value to integer
  583. /// value and checks if the resulting value is within a range of a
  584. /// target type. The target type should be one of the supported
  585. /// integer types.
  586. ///
  587. /// @param value_str input value given as string.
  588. /// @tparam T target integer type for lexical cast.
  589. ///
  590. /// @return Integer value after conversion from the string.
  591. /// @throw isc::dhcp::BadDataTypeCast if conversion was not successful.
  592. template<typename T>
  593. T lexicalCastWithRangeCheck(const std::string& value_str) const;
  594. /// @brief Write the string value into the provided buffer.
  595. ///
  596. /// This method writes the given value to the specified buffer.
  597. /// The provided string value may represent data of different types.
  598. /// The actual data type is specified with the second argument.
  599. /// Based on a value of this argument, this function will first
  600. /// try to cast the string value to the particular data type and
  601. /// if it is successful it will store the data in the buffer
  602. /// in a binary format.
  603. ///
  604. /// @param value string representation of the value to be written.
  605. /// @param type the actual data type to be stored.
  606. /// @param [in, out] buf buffer where the value is to be stored.
  607. ///
  608. /// @throw BadDataTypeCast if data write was unsuccessful.
  609. void writeToBuffer(const std::string& value, const OptionDataType type,
  610. OptionBuffer& buf) const;
  611. /// Option name.
  612. std::string name_;
  613. /// Option code.
  614. uint16_t code_;
  615. /// Option data type.
  616. OptionDataType type_;
  617. /// Indicates wheter option is a single value or array.
  618. bool array_type_;
  619. /// Name of the space being encapsulated by this option.
  620. std::string encapsulated_space_;
  621. /// Collection of data fields within the record.
  622. RecordFieldsCollection record_fields_;
  623. };
  624. /// @brief Multi index container for DHCP option definitions.
  625. ///
  626. /// This container allows to search for DHCP option definition
  627. /// using two indexes:
  628. /// - sequenced: used to access elements in the order they have
  629. /// been added to the container
  630. /// - option code: used to search definitions of options
  631. /// with a specified option code (aka option type).
  632. /// Note that this container can hold multiple options with the
  633. /// same code. For this reason, the latter index can be used to
  634. /// obtain a range of options for a particular option code.
  635. ///
  636. /// @todo: need an index to search options using option space name
  637. /// once option spaces are implemented.
  638. typedef boost::multi_index_container<
  639. // Container comprises elements of OptionDefinition type.
  640. OptionDefinitionPtr,
  641. // Here we start enumerating various indexes.
  642. boost::multi_index::indexed_by<
  643. // Sequenced index allows accessing elements in the same way
  644. // as elements in std::list. Sequenced is an index #0.
  645. boost::multi_index::sequenced<>,
  646. // Start definition of index #1.
  647. boost::multi_index::hashed_non_unique<
  648. // Use option type as the index key. The type is held
  649. // in OptionDefinition object so we have to call
  650. // OptionDefinition::getCode to retrieve this key
  651. // for each element. The option code is non-unique so
  652. // multiple elements with the same option code can
  653. // be returned by this index.
  654. boost::multi_index::const_mem_fun<
  655. OptionDefinition,
  656. uint16_t,
  657. &OptionDefinition::getCode
  658. >
  659. >,
  660. // Start definition of index #2
  661. boost::multi_index::hashed_non_unique<
  662. // Use option name as the index key. This value is
  663. // returned by the @c OptionDefinition::getName
  664. // method.
  665. boost::multi_index::const_mem_fun<
  666. OptionDefinition,
  667. std::string,
  668. &OptionDefinition::getName
  669. >
  670. >
  671. >
  672. > OptionDefContainer;
  673. /// Pointer to an option definition container.
  674. typedef boost::shared_ptr<OptionDefContainer> OptionDefContainerPtr;
  675. /// Container that holds various vendor option containers
  676. typedef std::map<uint32_t, OptionDefContainer> VendorOptionDefContainers;
  677. /// Type of the index #1 - option type.
  678. typedef OptionDefContainer::nth_index<1>::type OptionDefContainerTypeIndex;
  679. /// Pair of iterators to represent the range of options definitions
  680. /// having the same option type value. The first element in this pair
  681. /// represents the beginning of the range, the second element
  682. /// represents the end.
  683. typedef std::pair<OptionDefContainerTypeIndex::const_iterator,
  684. OptionDefContainerTypeIndex::const_iterator> OptionDefContainerTypeRange;
  685. /// Type of the index #2 - option name.
  686. typedef OptionDefContainer::nth_index<2>::type OptionDefContainerNameIndex;
  687. /// Pair of iterators to represent the range of options definitions
  688. /// having the same option name. The first element in this pair
  689. /// represents the beginning of the range, the second element
  690. /// represents the end.
  691. typedef std::pair<OptionDefContainerNameIndex::const_iterator,
  692. OptionDefContainerNameIndex::const_iterator> OptionDefContainerNameRange;
  693. } // namespace isc::dhcp
  694. } // namespace isc
  695. #endif // OPTION_DEFINITION_H