summaryrefslogtreecommitdiffstats
path: root/src/lib/hooks/library_manager_collection.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/hooks/library_manager_collection.h')
-rw-r--r--src/lib/hooks/library_manager_collection.h187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/lib/hooks/library_manager_collection.h b/src/lib/hooks/library_manager_collection.h
new file mode 100644
index 0000000..53a9669
--- /dev/null
+++ b/src/lib/hooks/library_manager_collection.h
@@ -0,0 +1,187 @@
+// Copyright (C) 2013-2020 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 LIBRARY_MANAGER_COLLECTION_H
+#define LIBRARY_MANAGER_COLLECTION_H
+
+#include <exceptions/exceptions.h>
+
+#include <boost/shared_ptr.hpp>
+#include <hooks/libinfo.h>
+
+#include <vector>
+
+namespace isc {
+namespace hooks {
+
+/// @brief LoadLibraries not called
+///
+/// Thrown if an attempt is made get a CalloutManager before the libraries
+/// have been loaded.
+class LoadLibrariesNotCalled : public Exception {
+public:
+ LoadLibrariesNotCalled(const char* file, size_t line, const char* what) :
+ isc::Exception(file, line, what) {}
+};
+
+
+// Forward declarations
+class CalloutManager;
+class LibraryManager;
+
+/// @brief Library manager collection
+///
+/// The LibraryManagerCollection class, as the name implies, is responsible for
+/// managing the collection of LibraryManager objects that describe the loaded
+/// libraries. As such, it converts a single operation (e.g load libraries)
+/// into multiple operations, one per library. However, the class does more
+/// than that - it provides a single object with which to manage lifetimes.
+///
+/// As described in the LibraryManager documentation, a CalloutHandle may end
+/// up with pointers to memory within the address space of a loaded library.
+/// If the library is closed before this address space is deleted, the
+/// deletion of the CalloutHandle may attempt to free memory into the newly-
+/// unmapped address space and cause a segmentation fault.
+///
+/// To prevent this, each CalloutHandle maintains a shared pointer to the
+/// LibraryManagerCollection current when it was created. In addition, the
+/// containing HooksManager object also maintains a shared pointer to it.
+/// A LibraryManagerCollection is never explicitly deleted: when a new set
+/// of libraries is loaded, the HooksManager clears its pointer to the
+/// collection. The LibraryManagerCollection is only destroyed when all
+/// CallHandle objects referencing it are destroyed.
+///
+/// Note that this does not completely solve the problem - a hook function may
+/// have modified a packet being processed by the server and that packet may
+/// hold a pointer to memory in the library's virtual address space. To avoid
+/// a segmentation fault, that packet needs to free the memory before the
+/// LibraryManagerCollection is destroyed and this places demands on the server
+/// code. However, the link with the CalloutHandle does at least mean that
+/// authors of server code do not need to be so careful about when they destroy
+/// CalloutHandles.
+///
+/// The collection object also provides a utility function to validate a set
+/// of libraries. The function checks that each library exists, can be opened,
+/// that the "version" function exists and return the right number.
+
+class LibraryManagerCollection {
+public:
+ /// @brief Constructor
+ ///
+ /// @param libraries List of libraries that this collection will manage.
+ /// The order of the libraries is important. It holds the library
+ /// names and its configuration parameters.
+ LibraryManagerCollection(const HookLibsCollection& libraries);
+
+ /// @brief Destructor
+ ///
+ /// Unloads all loaded libraries.
+ ~LibraryManagerCollection() {
+ static_cast<void>(unloadLibraries());
+ }
+
+ /// @brief Load libraries
+ ///
+ /// Loads the libraries. This creates the LibraryManager associated with
+ /// each library and calls its loadLibrary() method. If a library fails
+ /// to load, the loading is abandoned and all libraries loaded so far
+ /// are unloaded.
+ ///
+ /// @return true if all libraries loaded, false if one or more failed t
+ //// load.
+ bool loadLibraries();
+
+ /// @brief Get callout manager
+ ///
+ /// Returns a callout manager that can be used with this set of loaded
+ /// libraries (even if the number of loaded libraries is zero). This
+ /// method may only be called after loadLibraries() has been called.
+ ///
+ /// @return Pointer to a callout manager for this set of libraries.
+ ///
+ /// @throw LoadLibrariesNotCalled Thrown if this method is called between
+ /// construction and the time loadLibraries() is called.
+ boost::shared_ptr<CalloutManager> getCalloutManager() const;
+
+ /// @brief Get library names
+ ///
+ /// Returns the list of library names. If called before loadLibraries(),
+ /// the list is the list of names to be loaded; if called afterwards, it
+ /// is the list of libraries that have been loaded.
+ std::vector<std::string> getLibraryNames() const {
+ return (library_names_);
+ }
+
+ /// @brief Returns library info
+ ///
+ /// Returns a collection of libraries, each entry consisting of a library
+ /// name + all its parameters.
+ HookLibsCollection getLibraryInfo() const {
+ return (library_info_);
+ }
+
+ /// @brief Get number of loaded libraries
+ ///
+ /// Mainly for testing, this returns the number of libraries that are
+ /// loaded.
+ ///
+ /// @return Number of libraries that are loaded.
+ int getLoadedLibraryCount() const;
+
+ /// @brief Validate libraries
+ ///
+ /// Utility function to validate libraries. It checks that the libraries
+ /// exist, can be opened, that a "version" function is present in them, and
+ /// that it returns the right number. All errors are logged.
+ ///
+ /// @param libraries List of libraries to validate
+ ///
+ /// @return Vector of libraries that failed to validate, or an empty vector
+ /// if all validated.
+ static std::vector<std::string>
+ validateLibraries(const std::vector<std::string>& libraries);
+
+ /// @brief Prepare libaries unloading
+ ///
+ /// Utility function to call before closing libraries. It runs the
+ /// unload() function when it exists and removes associated callout.
+ /// When this function returns either there is only one owner
+ /// (the hook manager) or some visible dangling pointers so
+ /// libraries are not closed to lower the probability of a crash.
+ /// See @ref LibraryManager::prepareUnloadLibrary.
+ ///
+ /// @return true if all libraries unload were not found or run
+ /// successfully, false on an error.
+ bool prepareUnloadLibraries();
+
+protected:
+ /// @brief Unload libraries
+ ///
+ /// Unloads and closes all loaded libraries. They are unloaded in the
+ /// reverse order to the order in which they were loaded.
+ void unloadLibraries();
+
+private:
+
+ /// Vector of library names
+ std::vector<std::string> library_names_;
+
+ /// Vector of library managers
+ std::vector<boost::shared_ptr<LibraryManager> > lib_managers_;
+
+ /// Vector of library information. Each piece of information
+ /// consists of a pair of (library name, library parameters)
+ HookLibsCollection library_info_;
+
+ /// Callout manager to be associated with the libraries
+ boost::shared_ptr<CalloutManager> callout_manager_;
+};
+
+} // namespace hooks
+} // namespace isc
+
+
+#endif // LIBRARY_MANAGER_COLLECTION_H