// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef LIBDHCP_H #define LIBDHCP_H #include #include #include #include #include #include #include #include #include namespace isc { namespace dhcp { class LibDHCP { public: /// Map of factory functions. typedef std::map FactoryMap; /// @brief Returns collection of option definitions. /// /// This method returns a collection of option definitions for a specified /// option space. /// /// @param space Option space. /// /// @return Pointer to a collection of option definitions. static const OptionDefContainerPtr& getOptionDefs(const std::string& space); /// @brief Return the first option definition matching a /// particular option code. /// /// @param space option space. /// @param code option code. /// /// @return reference to an option definition being requested /// or NULL pointer if option definition has not been found. static OptionDefinitionPtr getOptionDef(const std::string& space, const uint16_t code); /// @brief Return the definition of option having a specified name. /// /// @param space option space. /// @param name Option name. /// /// @return Pointer to the option definition or NULL pointer if option /// definition has not been found. static OptionDefinitionPtr getOptionDef(const std::string& space, const std::string& name); /// @brief Returns vendor option definition for a given vendor-id and code /// /// @param u universe (V4 or V6) /// @param vendor_id enterprise-id for a given vendor /// @param code option code /// @return reference to an option definition being requested /// or NULL pointer if option definition has not been found. static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, const uint16_t code); /// @brief Returns vendor option definition for a given vendor-id and /// option name. /// /// @param u Universe (V4 or V6) /// @param vendor_id Enterprise-id for a given vendor /// @param name Option name. /// /// @return A pointer to an option definition or NULL pointer if /// no option definition found. static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, const std::string& name); /// @brief Returns runtime (non-standard) option definition by space and /// option code. /// /// @param space Option space name. /// @param code Option code. /// /// @return Pointer to option definition or NULL if it doesn't exist. static OptionDefinitionPtr getRuntimeOptionDef(const std::string& space, const uint16_t code); /// @brief Returns runtime (non-standard) option definition by space and /// option name. /// /// @param space Option space name. /// @param name Option name. /// /// @return Pointer to option definition or NULL if it doesn't exist. static OptionDefinitionPtr getRuntimeOptionDef(const std::string& space, const std::string& name); /// @brief Returns runtime (non-standard) option definitions for specified /// option space name. /// /// @param space Option space name. /// /// @return Pointer to the container holding option definitions or NULL. static OptionDefContainerPtr getRuntimeOptionDefs(const std::string& space); /// @brief Checks if an option unpacking has to be deferred. /// /// DHCPv4 option 43 and 224-254 unpacking is done after classification. /// /// @space Option space name. /// @param code Option code. /// /// @return True if option processing should be deferred. static bool deferOption(const std::string& space, const uint16_t code); /// @brief Last resort definition for DHCPv4 option 43 static OptionDefinitionPtr last_resort_option43_def; /// @brief Factory function to create instance of option. /// /// Factory method creates instance of specified option. The option /// to be created has to have corresponding factory function /// registered with \ref LibDHCP::OptionFactoryRegister. /// /// @param u universe of the option (V4 or V6) /// @param type option-type /// @param buf option-buffer /// /// @return instance of option. /// /// @throw isc::InvalidOperation if there is no factory function registered /// for the specified option type. static isc::dhcp::OptionPtr optionFactory(isc::dhcp::Option::Universe u, uint16_t type, const OptionBuffer& buf); /// @brief Stores DHCPv4 options in a buffer. /// /// Stores all options defined in options containers in a on-wire /// format in output buffer specified by buf. /// /// May throw different exceptions if option assembly fails. There /// may be different reasons (option too large, option malformed, /// too many options etc.) /// /// This is v4 specific version, which stores Relay Agent Information /// option and END options last. /// /// @param buf output buffer (assembled options will be stored here) /// @param options collection of options to store to static void packOptions4(isc::util::OutputBuffer& buf, const isc::dhcp::OptionCollection& options); /// @brief Stores DHCPv6 options in a buffer. /// /// Stores all options defined in options containers in a on-wire /// format in output buffer specified by buf. /// /// May throw different exceptions if option assembly fails. There /// may be different reasons (option too large, option malformed, /// too many options etc.) /// /// Currently there's no special logic in it. Options are stored in /// the order of their option codes. /// /// @param buf output buffer (assembled options will be stored here) /// @param options collection of options to store to static void packOptions6(isc::util::OutputBuffer& buf, const isc::dhcp::OptionCollection& options); /// @brief Parses provided buffer as DHCPv6 options and creates /// Option objects. /// /// Parses provided buffer and stores created Option objects in /// options container. The last two parameters are optional and /// are used in relay parsing. If they are specified, relay-msg /// option is not created, but rather those two parameters are /// specified to point out where the relay-msg option resides and /// what is its length. This is a performance optimization that /// avoids unnecessary copying of potentially large relay-msg /// option. It is not used for anything, except in the next /// iteration its content will be treated as buffer to be parsed. /// /// @param buf Buffer to be parsed. /// @param option_space A name of the option space which holds definitions /// to be used to parse options in the packets. /// @param options Reference to option container. Options will be /// put here. /// @param relay_msg_offset reference to a size_t structure. If specified, /// offset to beginning of relay_msg option will be stored in it. /// @param relay_msg_len reference to a size_t structure. If specified, /// length of the relay_msg option will be stored in it. /// @return offset to the first byte after the last successfully /// parsed option /// /// @note This function throws when an option type is defined more /// than once, and it calls option building routines which can throw. /// Partial parsing does not throw: it is the responsibility of the /// caller to handle this condition. static size_t unpackOptions6(const OptionBuffer& buf, const std::string& option_space, isc::dhcp::OptionCollection& options, size_t* relay_msg_offset = 0, size_t* relay_msg_len = 0); /// @brief Parses provided buffer as DHCPv4 options and creates /// Option objects. /// /// Parses provided buffer and stores created Option objects /// in options container. /// /// @param buf Buffer to be parsed. /// @param option_space A name of the option space which holds definitions /// to be used to parse options in the packets. /// @param options Reference to option container. Options will be /// put here. /// @param deferred Reference to an option code list. Options which /// processing is deferred will be put here. /// @return offset to the first byte after the last successfully /// parsed option or the offset of the DHO_END option type. /// /// The unpackOptions6 note applies too. static size_t unpackOptions4(const OptionBuffer& buf, const std::string& option_space, isc::dhcp::OptionCollection& options, std::list& deferred); /// Registers factory method that produces options of specific option types. /// /// @throw isc::BadValue if provided the type is already registered, has /// too large a value or an invalid universe is specified. /// /// @param u universe of the option (V4 or V6) /// @param type option-type /// @param factory function pointer static void OptionFactoryRegister(Option::Universe u, uint16_t type, Option::Factory * factory); /// @brief Returns v4 option definitions for a given vendor /// /// @param vendor_id enterprise-id of a given vendor /// @return a container for a given vendor (or NULL if no option /// definitions are defined) static const OptionDefContainerPtr& getVendorOption4Defs(const uint32_t vendor_id); /// @brief Returns v6 option definitions for a given vendor /// /// @param vendor_id enterprise-id of a given vendor /// @return a container for a given vendor (or NULL if no option /// definitions are defined) static const OptionDefContainerPtr& getVendorOption6Defs(const uint32_t vendor_id); /// @brief Parses provided buffer as DHCPv6 vendor options and creates /// Option objects. /// /// Parses provided buffer and stores created Option objects /// in options container. /// /// @param vendor_id enterprise-id of the vendor /// @param buf Buffer to be parsed. /// @param options Reference to option container. Suboptions will be /// put here. /// @return offset to the first byte after the last successfully /// parsed suboption /// /// @note unpackVendorOptions6 throws when it fails to parse a suboption /// so the return value is currently always the buffer length. static size_t unpackVendorOptions6(const uint32_t vendor_id, const OptionBuffer& buf, isc::dhcp::OptionCollection& options); /// @brief Parses provided buffer as DHCPv4 vendor options and creates /// Option objects. /// /// Parses provided buffer and stores created Option objects /// in options container. /// /// @param vendor_id enterprise-id of the vendor /// @param buf Buffer to be parsed. /// @param options Reference to option container. Suboptions will be /// put here. /// @return offset to the first byte after the last successfully /// parsed suboption /// /// The unpackVendorOptions6 note applies static size_t unpackVendorOptions4(const uint32_t vendor_id, const OptionBuffer& buf, isc::dhcp::OptionCollection& options); /// @brief Copies option definitions created at runtime. /// /// Copied option definitions will be used as "runtime" option definitions. /// A typical use case is to set option definitions specified by the user /// in the server configuration. These option definitions should be removed /// or replaced with new option definitions upon reconfiguration. /// /// @param defs Const reference to a container holding option definitions /// grouped by option spaces. static void setRuntimeOptionDefs(const OptionDefSpaceContainer& defs); /// @brief Removes runtime option definitions. static void clearRuntimeOptionDefs(); /// @brief Reverts uncommitted changes to runtime option definitions. static void revertRuntimeOptionDefs(); /// @brief Commits runtime option definitions. static void commitRuntimeOptionDefs(); /// @brief Converts option space name to vendor id. /// /// If the option space name is specified in the following format: /// "vendor-X" where X is an uint32_t number, it is assumed to be /// a vendor space and the uint32_t number is returned by this function. /// If the option space name is invalid this method will return 0, which /// is not a valid vendor-id, to signal an error. /// /// @todo remove this function once when the conversion is dealt by the /// appropriate functions returning options by option space names. /// /// @param option_space Option space name. /// @return vendor id. static uint32_t optionSpaceToVendorId(const std::string& option_space); private: /// Initialize standard DHCPv4 option definitions. /// /// The method creates option definitions for all DHCPv4 options. /// Currently this function is not implemented. /// /// @throw std::bad alloc if system went out of memory. /// @throw MalformedOptionDefinition if any of the definitions /// are incorrect. This is programming error. static void initStdOptionDefs4(); /// Initialize standard DHCPv6 option definitions. /// /// The method creates option definitions for all DHCPv6 options. /// /// @throw std::bad_alloc if system went out of memory. /// @throw MalformedOptionDefinition if any of the definitions /// is incorrect. This is a programming error. static void initStdOptionDefs6(); static void initVendorOptsDocsis4(); static void initVendorOptsDocsis6(); /// Initialize private DHCPv6 option definitions. static void initVendorOptsIsc6(); /// pointers to factories that produce DHCPv6 options static FactoryMap v4factories_; /// pointers to factories that produce DHCPv6 options static FactoryMap v6factories_; /// Container with DHCPv4 option definitions. static OptionDefContainerPtr v4option_defs_; /// Container with DHCPv6 option definitions. static OptionDefContainerPtr v6option_defs_; /// Container that holds option definitions for various option spaces. static OptionDefContainers option_defs_; /// Container for v4 vendor option definitions static VendorOptionDefContainers vendor4_defs_; /// Container for v6 vendor option definitions static VendorOptionDefContainers vendor6_defs_; /// Container for additional option definitions created in runtime. static util::StagedValue runtime_option_defs_; }; } } #endif // LIBDHCP_H