libdhcp++.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. // Copyright (C) 2011-2017 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 LIBDHCP_H
  7. #define LIBDHCP_H
  8. #include <dhcp/option_definition.h>
  9. #include <dhcp/option_space_container.h>
  10. #include <dhcp/pkt4.h>
  11. #include <dhcp/pkt6.h>
  12. #include <util/buffer.h>
  13. #include <util/staged_value.h>
  14. #include <iostream>
  15. #include <stdint.h>
  16. #include <string>
  17. namespace isc {
  18. namespace dhcp {
  19. class LibDHCP {
  20. public:
  21. /// Map of factory functions.
  22. typedef std::map<unsigned short, Option::Factory*> FactoryMap;
  23. /// @brief Returns collection of option definitions.
  24. ///
  25. /// This method returns a collection of option definitions for a specified
  26. /// option space.
  27. ///
  28. /// @param space Option space.
  29. ///
  30. /// @return Pointer to a collection of option definitions.
  31. static const OptionDefContainerPtr& getOptionDefs(const std::string& space);
  32. /// @brief Return the first option definition matching a
  33. /// particular option code.
  34. ///
  35. /// @param space option space.
  36. /// @param code option code.
  37. ///
  38. /// @return reference to an option definition being requested
  39. /// or NULL pointer if option definition has not been found.
  40. static OptionDefinitionPtr getOptionDef(const std::string& space,
  41. const uint16_t code);
  42. /// @brief Return the definition of option having a specified name.
  43. ///
  44. /// @param space option space.
  45. /// @param name Option name.
  46. ///
  47. /// @return Pointer to the option definition or NULL pointer if option
  48. /// definition has not been found.
  49. static OptionDefinitionPtr getOptionDef(const std::string& space,
  50. const std::string& name);
  51. /// @brief Returns vendor option definition for a given vendor-id and code
  52. ///
  53. /// @param u universe (V4 or V6)
  54. /// @param vendor_id enterprise-id for a given vendor
  55. /// @param code option code
  56. /// @return reference to an option definition being requested
  57. /// or NULL pointer if option definition has not been found.
  58. static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u,
  59. const uint32_t vendor_id,
  60. const uint16_t code);
  61. /// @brief Returns vendor option definition for a given vendor-id and
  62. /// option name.
  63. ///
  64. /// @param u Universe (V4 or V6)
  65. /// @param vendor_id Enterprise-id for a given vendor
  66. /// @param name Option name.
  67. ///
  68. /// @return A pointer to an option definition or NULL pointer if
  69. /// no option definition found.
  70. static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u,
  71. const uint32_t vendor_id,
  72. const std::string& name);
  73. /// @brief Returns runtime (non-standard) option definition by space and
  74. /// option code.
  75. ///
  76. /// @param space Option space name.
  77. /// @param code Option code.
  78. ///
  79. /// @return Pointer to option definition or NULL if it doesn't exist.
  80. static OptionDefinitionPtr getRuntimeOptionDef(const std::string& space,
  81. const uint16_t code);
  82. /// @brief Returns runtime (non-standard) option definition by space and
  83. /// option name.
  84. ///
  85. /// @param space Option space name.
  86. /// @param name Option name.
  87. ///
  88. /// @return Pointer to option definition or NULL if it doesn't exist.
  89. static OptionDefinitionPtr getRuntimeOptionDef(const std::string& space,
  90. const std::string& name);
  91. /// @brief Returns runtime (non-standard) option definitions for specified
  92. /// option space name.
  93. ///
  94. /// @param space Option space name.
  95. ///
  96. /// @return Pointer to the container holding option definitions or NULL.
  97. static OptionDefContainerPtr
  98. getRuntimeOptionDefs(const std::string& space);
  99. /// @brief Checks if an option unpacking has to be deferred.
  100. ///
  101. /// DHCPv4 option 43 and 224-254 unpacking is done after classification.
  102. ///
  103. /// @space Option space name.
  104. /// @param code Option code.
  105. ///
  106. /// @return True if option processing should be deferred.
  107. static bool deferOption(const std::string& space, const uint16_t code);
  108. /// @brief Last resort definition for DHCPv4 option 43
  109. static OptionDefinitionPtr last_resort_option43_def;
  110. /// @brief Factory function to create instance of option.
  111. ///
  112. /// Factory method creates instance of specified option. The option
  113. /// to be created has to have corresponding factory function
  114. /// registered with \ref LibDHCP::OptionFactoryRegister.
  115. ///
  116. /// @param u universe of the option (V4 or V6)
  117. /// @param type option-type
  118. /// @param buf option-buffer
  119. ///
  120. /// @return instance of option.
  121. ///
  122. /// @throw isc::InvalidOperation if there is no factory function registered
  123. /// for the specified option type.
  124. static isc::dhcp::OptionPtr optionFactory(isc::dhcp::Option::Universe u,
  125. uint16_t type,
  126. const OptionBuffer& buf);
  127. /// @brief Stores DHCPv4 options in a buffer.
  128. ///
  129. /// Stores all options defined in options containers in a on-wire
  130. /// format in output buffer specified by buf.
  131. ///
  132. /// May throw different exceptions if option assembly fails. There
  133. /// may be different reasons (option too large, option malformed,
  134. /// too many options etc.)
  135. ///
  136. /// This is v4 specific version, which stores Relay Agent Information
  137. /// option and END options last.
  138. ///
  139. /// @param buf output buffer (assembled options will be stored here)
  140. /// @param options collection of options to store to
  141. static void packOptions4(isc::util::OutputBuffer& buf,
  142. const isc::dhcp::OptionCollection& options);
  143. /// @brief Stores DHCPv6 options in a buffer.
  144. ///
  145. /// Stores all options defined in options containers in a on-wire
  146. /// format in output buffer specified by buf.
  147. ///
  148. /// May throw different exceptions if option assembly fails. There
  149. /// may be different reasons (option too large, option malformed,
  150. /// too many options etc.)
  151. ///
  152. /// Currently there's no special logic in it. Options are stored in
  153. /// the order of their option codes.
  154. ///
  155. /// @param buf output buffer (assembled options will be stored here)
  156. /// @param options collection of options to store to
  157. static void packOptions6(isc::util::OutputBuffer& buf,
  158. const isc::dhcp::OptionCollection& options);
  159. /// @brief Parses provided buffer as DHCPv6 options and creates
  160. /// Option objects.
  161. ///
  162. /// Parses provided buffer and stores created Option objects in
  163. /// options container. The last two parameters are optional and
  164. /// are used in relay parsing. If they are specified, relay-msg
  165. /// option is not created, but rather those two parameters are
  166. /// specified to point out where the relay-msg option resides and
  167. /// what is its length. This is a performance optimization that
  168. /// avoids unnecessary copying of potentially large relay-msg
  169. /// option. It is not used for anything, except in the next
  170. /// iteration its content will be treated as buffer to be parsed.
  171. ///
  172. /// @param buf Buffer to be parsed.
  173. /// @param option_space A name of the option space which holds definitions
  174. /// to be used to parse options in the packets.
  175. /// @param options Reference to option container. Options will be
  176. /// put here.
  177. /// @param relay_msg_offset reference to a size_t structure. If specified,
  178. /// offset to beginning of relay_msg option will be stored in it.
  179. /// @param relay_msg_len reference to a size_t structure. If specified,
  180. /// length of the relay_msg option will be stored in it.
  181. /// @return offset to the first byte after the last successfully
  182. /// parsed option
  183. ///
  184. /// @note This function throws when an option type is defined more
  185. /// than once, and it calls option building routines which can throw.
  186. /// Partial parsing does not throw: it is the responsibility of the
  187. /// caller to handle this condition.
  188. static size_t unpackOptions6(const OptionBuffer& buf,
  189. const std::string& option_space,
  190. isc::dhcp::OptionCollection& options,
  191. size_t* relay_msg_offset = 0,
  192. size_t* relay_msg_len = 0);
  193. /// @brief Parses provided buffer as DHCPv4 options and creates
  194. /// Option objects.
  195. ///
  196. /// Parses provided buffer and stores created Option objects
  197. /// in options container.
  198. ///
  199. /// @param buf Buffer to be parsed.
  200. /// @param option_space A name of the option space which holds definitions
  201. /// to be used to parse options in the packets.
  202. /// @param options Reference to option container. Options will be
  203. /// put here.
  204. /// @param deferred Reference to an option code list. Options which
  205. /// processing is deferred will be put here.
  206. /// @return offset to the first byte after the last successfully
  207. /// parsed option or the offset of the DHO_END option type.
  208. ///
  209. /// The unpackOptions6 note applies too.
  210. static size_t unpackOptions4(const OptionBuffer& buf,
  211. const std::string& option_space,
  212. isc::dhcp::OptionCollection& options,
  213. std::list<uint16_t>& deferred);
  214. /// Registers factory method that produces options of specific option types.
  215. ///
  216. /// @throw isc::BadValue if provided the type is already registered, has
  217. /// too large a value or an invalid universe is specified.
  218. ///
  219. /// @param u universe of the option (V4 or V6)
  220. /// @param type option-type
  221. /// @param factory function pointer
  222. static void OptionFactoryRegister(Option::Universe u,
  223. uint16_t type,
  224. Option::Factory * factory);
  225. /// @brief Returns v4 option definitions for a given vendor
  226. ///
  227. /// @param vendor_id enterprise-id of a given vendor
  228. /// @return a container for a given vendor (or NULL if no option
  229. /// definitions are defined)
  230. static const OptionDefContainerPtr&
  231. getVendorOption4Defs(const uint32_t vendor_id);
  232. /// @brief Returns v6 option definitions for a given vendor
  233. ///
  234. /// @param vendor_id enterprise-id of a given vendor
  235. /// @return a container for a given vendor (or NULL if no option
  236. /// definitions are defined)
  237. static const OptionDefContainerPtr&
  238. getVendorOption6Defs(const uint32_t vendor_id);
  239. /// @brief Parses provided buffer as DHCPv6 vendor options and creates
  240. /// Option objects.
  241. ///
  242. /// Parses provided buffer and stores created Option objects
  243. /// in options container.
  244. ///
  245. /// @param vendor_id enterprise-id of the vendor
  246. /// @param buf Buffer to be parsed.
  247. /// @param options Reference to option container. Suboptions will be
  248. /// put here.
  249. /// @return offset to the first byte after the last successfully
  250. /// parsed suboption
  251. ///
  252. /// @note unpackVendorOptions6 throws when it fails to parse a suboption
  253. /// so the return value is currently always the buffer length.
  254. static size_t unpackVendorOptions6(const uint32_t vendor_id,
  255. const OptionBuffer& buf,
  256. isc::dhcp::OptionCollection& options);
  257. /// @brief Parses provided buffer as DHCPv4 vendor options and creates
  258. /// Option objects.
  259. ///
  260. /// Parses provided buffer and stores created Option objects
  261. /// in options container.
  262. ///
  263. /// @param vendor_id enterprise-id of the vendor
  264. /// @param buf Buffer to be parsed.
  265. /// @param options Reference to option container. Suboptions will be
  266. /// put here.
  267. /// @return offset to the first byte after the last successfully
  268. /// parsed suboption
  269. ///
  270. /// The unpackVendorOptions6 note applies
  271. static size_t unpackVendorOptions4(const uint32_t vendor_id,
  272. const OptionBuffer& buf,
  273. isc::dhcp::OptionCollection& options);
  274. /// @brief Copies option definitions created at runtime.
  275. ///
  276. /// Copied option definitions will be used as "runtime" option definitions.
  277. /// A typical use case is to set option definitions specified by the user
  278. /// in the server configuration. These option definitions should be removed
  279. /// or replaced with new option definitions upon reconfiguration.
  280. ///
  281. /// @param defs Const reference to a container holding option definitions
  282. /// grouped by option spaces.
  283. static void setRuntimeOptionDefs(const OptionDefSpaceContainer& defs);
  284. /// @brief Removes runtime option definitions.
  285. static void clearRuntimeOptionDefs();
  286. /// @brief Reverts uncommitted changes to runtime option definitions.
  287. static void revertRuntimeOptionDefs();
  288. /// @brief Commits runtime option definitions.
  289. static void commitRuntimeOptionDefs();
  290. /// @brief Converts option space name to vendor id.
  291. ///
  292. /// If the option space name is specified in the following format:
  293. /// "vendor-X" where X is an uint32_t number, it is assumed to be
  294. /// a vendor space and the uint32_t number is returned by this function.
  295. /// If the option space name is invalid this method will return 0, which
  296. /// is not a valid vendor-id, to signal an error.
  297. ///
  298. /// @todo remove this function once when the conversion is dealt by the
  299. /// appropriate functions returning options by option space names.
  300. ///
  301. /// @param option_space Option space name.
  302. /// @return vendor id.
  303. static uint32_t optionSpaceToVendorId(const std::string& option_space);
  304. private:
  305. /// Initialize standard DHCPv4 option definitions.
  306. ///
  307. /// The method creates option definitions for all DHCPv4 options.
  308. /// Currently this function is not implemented.
  309. ///
  310. /// @throw std::bad alloc if system went out of memory.
  311. /// @throw MalformedOptionDefinition if any of the definitions
  312. /// are incorrect. This is programming error.
  313. static void initStdOptionDefs4();
  314. /// Initialize standard DHCPv6 option definitions.
  315. ///
  316. /// The method creates option definitions for all DHCPv6 options.
  317. ///
  318. /// @throw std::bad_alloc if system went out of memory.
  319. /// @throw MalformedOptionDefinition if any of the definitions
  320. /// is incorrect. This is a programming error.
  321. static void initStdOptionDefs6();
  322. static void initVendorOptsDocsis4();
  323. static void initVendorOptsDocsis6();
  324. /// Initialize private DHCPv6 option definitions.
  325. static void initVendorOptsIsc6();
  326. /// pointers to factories that produce DHCPv6 options
  327. static FactoryMap v4factories_;
  328. /// pointers to factories that produce DHCPv6 options
  329. static FactoryMap v6factories_;
  330. /// Container with DHCPv4 option definitions.
  331. static OptionDefContainerPtr v4option_defs_;
  332. /// Container with DHCPv6 option definitions.
  333. static OptionDefContainerPtr v6option_defs_;
  334. /// Container that holds option definitions for various option spaces.
  335. static OptionDefContainers option_defs_;
  336. /// Container for v4 vendor option definitions
  337. static VendorOptionDefContainers vendor4_defs_;
  338. /// Container for v6 vendor option definitions
  339. static VendorOptionDefContainers vendor6_defs_;
  340. /// Container for additional option definitions created in runtime.
  341. static util::StagedValue<OptionDefSpaceContainer> runtime_option_defs_;
  342. };
  343. }
  344. }
  345. #endif // LIBDHCP_H