BIND 10 trac3063, updated. 1463b5017b2c3a0d512ac54f8e644156864452c6 [3063] First draft of a Hooks Framework maintenance manual

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Aug 14 12:47:04 UTC 2013


The branch, trac3063 has been updated
       via  1463b5017b2c3a0d512ac54f8e644156864452c6 (commit)
      from  fef265b2e3bfae238c91bfd820bed760efc748aa (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1463b5017b2c3a0d512ac54f8e644156864452c6
Author: Stephen Morris <stephen at isc.org>
Date:   Wed Aug 14 13:46:05 2013 +0100

    [3063] First draft of a Hooks Framework maintenance manual

-----------------------------------------------------------------------

Summary of changes:
 doc/devel/mainpage.dox                          |   10 +-
 src/lib/hooks/hooks_component_developer.dox     |    8 +-
 src/lib/hooks/hooks_maintenance.dox             |  270 +++++++++++++++++++++++
 src/lib/hooks/{hook_user.dox => hooks_user.dox} |    2 +-
 src/lib/hooks/images/HooksUml.dia               |  Bin 0 -> 2354 bytes
 src/lib/hooks/images/HooksUml.png               |  Bin 0 -> 13841 bytes
 6 files changed, 281 insertions(+), 9 deletions(-)
 create mode 100644 src/lib/hooks/hooks_maintenance.dox
 rename src/lib/hooks/{hook_user.dox => hooks_user.dox} (99%)
 create mode 100644 src/lib/hooks/images/HooksUml.dia
 create mode 100644 src/lib/hooks/images/HooksUml.png

-----------------------------------------------------------------------
diff --git a/doc/devel/mainpage.dox b/doc/devel/mainpage.dox
index 685d9e6..8ebd7d1 100644
--- a/doc/devel/mainpage.dox
+++ b/doc/devel/mainpage.dox
@@ -21,7 +21,7 @@
  *
  * If you wish to write "hook" code - code that is loaded by BIND 10 at
  * run-time and modifies its behavior you should read the section
- * @ref hookDevelopersGuide.
+ * @ref hooksdgDevelopersGuide.
  *
  * BIND 10 maintanenace information is divided into a number of sections
  * depending on focus.  DNS-specific issues are covered in the
@@ -30,16 +30,18 @@
  * specific to any protocol, are discussed in @ref miscellaneousTopics.
  *
  * If you are a user or system administrator, rather than software engineer,
- * you should read <a href="http://bind10.isc.org/docs/bind10-guide.html">BIND10
+ * you should read the
+ * <a href="http://bind10.isc.org/docs/bind10-guide.html">BIND10
  * Guide (Administrator Reference for BIND10)</a> instead.
  *
- * Regardless of your field of expertise, you are encouraged to visit
+ * Regardless of your field of expertise, you are encouraged to visit the
  * <a href="http://bind10.isc.org/">BIND10 webpage (http://bind10.isc.org)</a>
  * @section hooksFramework Hooks Framework
  * - @subpage hooksdgDevelopersGuide
  * - @subpage dhcpv4Hooks
  * - @subpage dhcpv6Hooks
  * - @subpage hooksComponentDeveloperGuide
+ * - @subpage hooksmgMaintenanceGuide
  *
  * @section dnsMaintenanceGuide DNS Maintenance Guide
  * - Authoritative DNS (todo)
@@ -69,7 +71,7 @@
  * - @subpage perfdhcpInternals
  * - @subpage libdhcp_ddns
  *
- * @section miscellaneousTopics Miscellaneous topics
+ * @section miscellaneousTopics Miscellaneous Topics
  * - @subpage LoggingApi
  *   - @subpage LoggingApiOverview
  *   - @subpage LoggingApiLoggerNames
diff --git a/src/lib/hooks/hook_user.dox b/src/lib/hooks/hook_user.dox
deleted file mode 100644
index a804720..0000000
--- a/src/lib/hooks/hook_user.dox
+++ /dev/null
@@ -1,1031 +0,0 @@
-// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-// Note: the prefix "hooksdg" to all labels is an abbreviation for "Hooks
-// Developer's Guide" and is used to prevent a clash with symbols in any
-// other Doxygen file.
-
-/**
- @page hooksdgDevelopersGuide Hook Developer's Guide
-
- @section hooksdgIntroduction Introduction
-
-Although the BIND 10 framework and its associated DNS and DHCP programs
-provide comprehensive functionality, there will be times when it does
-not quite do what you require: the processing has to be extended in some
-way to solve your problem.
-
-Since the BIND 10 source code is freely available (BIND 10 being an
-open-source project), one option is to modify it to do what
-you want.  Whilst perfectly feasible, there are drawbacks:
-
-- Although well-documented, BIND 10 is a large program.  Just
-understanding how it works will take a significant amount of time. In
-addition, despite the fact that its object-oriented design keeps the
-coupling between modules to a minimum, an inappropriate change to one
-part of the program during the extension could cause another to
-behave oddly or to stop working altogether.
-
-- The change may need to be re-applied or re-written with every new
-version of BIND 10.  As new functionality is added or bugs are fixed,
-the code or algorithms in the core software may change - and may change
-significantly.
-
-To overcome these problems, BIND 10 provides the "Hooks" interface -
-a defined interface for third-party or user-written code. (For ease of
-reference in the rest of this document, all such code will be referred
-to as "user code".)  At specific points in its processing
-("hook points") BIND 10 will make a call to this code.  The call passes
-data that the user code can examine and, if required, modify.
-BIND 10 uses the modified data in the remainder of its processing.
-
-In order to minimise the interaction between BIND 10 and the user
-code, the latter is built independently of BIND 10 in the form of
-a shared library (or libraries).  These are made known to BIND 10
-through its configuration mechanism, and BIND 10 loads the library at
-run time. Libraries can be unloaded and reloaded as needed while BIND
-10 is running.
-
-Use of a defined API and the BIND 10 configuration mechanism means that
-as new versions of BIND 10 are released, there is no need to modify
-the user code.  Unless there is a major change in an interface
-(which will be clearly documented), all that will be required is a rebuild
-of the libraries.
-
- at note Although the defined interface should not change, the internals
-of some of the classes and structures referenced by the user code may
-change between versions of BIND 10.  These changes have to be reflected
-in the compiled version of the software, hence the need for a rebuild.
-
- at subsection hooksdgLanguages Languages
-
-The core of BIND 10 is written in C++.  While it is the intention to
-provide interfaces into user code written in other languages, the initial
-versions of the Hooks system requires that user code be written in C++.
-All examples in this guide are in that language.
-
- at subsection hooksdgTerminology Terminology
-
-In the remainder of this guide, the following terminology is used:
-
-- Hook/Hook Point - used interchageably, this is a point in the code at
-which a call to user functions is made. Each hook has a name and
-each hook can have any number (including 0) of user functions
-attached to it.
-
-- Callout - a user function called by the server at a hook
-point. This is so-named because the server "calls out" to the library
-to execute a user function.
-
-- Framework function - the functions that a user library needs to
-supply in order for the hooks framework to load and unload the library.
-
-- User code/user library - non-BIND 10 code that is compiled into a
-shared library and loaded by BIND 10 into its address space.
-
-
- at section hooksdgTutorial Tutorial
-
-To illustrate how to write code that integrates with BIND 10, we will
-use the following (rather contrived) example:
-
-The BIND 10 DHCPv4 server is used to allocate IPv4 addresses to clients
-(as well as to pass them other information such as the address of DNS
-servers).  We will suppose that we need to classify clients requesting
-IPv4 addresses according to their hardware address, and want to log both
-the hardware address and allocated IP address for the clients of interest.
-
-The following sections describe how to implement these requirements.
-The code presented here is not efficient and there are better ways of
-doing the task.  The aim however, is to illustrate the main features of
-user hook code not to provide an optimal solution.
-
-
- at subsection hooksdgFrameworkFunctions Framework Functions
-
-Loading and initializing a library holding user code makes use
-of three (user-supplied) functions:
-
-- version - defines the version of BIND 10 code with which the user-library
-is built
-- load - called when the library is loaded by the server.
-- unload - called when the library is unloaded by the server.
-
-Of these, only "version" is mandatory, although in our example, all three
-are used.
-
- at subsubsection hooksdgVersionFunction The "version" Function
-
-"version" is used by the hooks framework to check that the libraries
-it is loading are compatible with the version of BIND 10 being run.
-Although the hooks system allows BIND 10 and user code to interface
-through a defined API, the relationship is somewhat tight in that the
-user code will depend on the internal structures of BIND 10.  If these
-change - as they can between BIND 10 releases - and BIND 10 is run with
-a version of user code built against an earlier version of BIND
-10, a program crash could result.
-
-To guard against this, the "version" function must be provided in every
-library.  It returns a constant defined in header files of the version
-of BIND 10 against which it was built.  The hooks framework checks this
-for compatibility with the running version of BIND 10 before loading
-the library.
-
-In this tutorial, we'll put "version" in its own file, version.cc.  The
-contents are:
-
- at code
-// version.cc
-
-#include <hooks/hooks.h>
-
-extern "C" {
-
-int version() {
-    return (BIND10_HOOKS_VERSION);
-}
-
-};
- at endcode
-
-The file "hooks/hooks.h" is specified relative to the BIND 10 libraries
-source directory - this is covered later in the section @ref hooksdgBuild.
-It defines the symbol BIND10_HOOKS_VERSION, which has a value that changes
-on every release of BIND 10: this is the value that needs to be returned
-to the hooks framework.
-
-A final point to note is that the definition of "version" is enclosed
-within 'extern "C"' braces.  All functions accessed by the hooks
-framework use C linkage, mainly to avoid the name mangling that
-accompanies use of the C++ compiler, but also to avoid issues related
-to namespaces.
-
- at subsubsection hooksdgLoadUnloadFunctions The "load" and "unload" Functions
-
-As the names suggest, "load" is called when a library is loaded and
-"unload" called when it is unloaded.  (It is always guaranteed that
-"load" is called: "unload" may not be called in some circumstances,
-e.g. if the system shuts down abnormally.)  These functions are the
-places where any library-wide resources are allocated and deallocated.
-"load" is also the place where any callouts with non-standard names
-(names that are not hook point names) can be registered:
-this is covered further in the section @ref hooksdgCalloutRegistration.
-
-The example does not make any use callouts with non-standard names.  However,
-as our design requires that the log file be open while BIND 10 is active
-and the library loaded, we'll open the file in the "load" function and close
-it in "unload".
-
-We create two files, one for the file handle declaration:
-
- at code
-// library_common.h
-
-#ifndef LIBRARY_COMMON_H
-#define LIBRARY_COMMON_H
-
-#include <fstream>
-
-// "Interesting clients" log file handle declaration.
-extern std::fstream interesting;
-
-#endif // LIBRARY_COMMON_H
- at endcode
-
-... and one to hold the "load" and "unload" functions:
-
- at code
-// load_unload.cc
-
-#include <hooks/hooks.h>
-#include "library_common.h"
-
-// "Interesting clients" log file handle definition.
-std::fstream interesting;
-
-extern "C" {
-
-int load(LibraryHandle&) {
-    interesting.open("/data/clients/interesting.log",
-                     std::fstream::out | std::fstream::app);
-    return (interesting ? 0 : 1);
-}
-
-int unload() {
-    if (interesting) {
-        interesting.close();
-    }
-    return (0);
-}
-
-};
- at endcode
-
-Notes:
-- The file handle ("interesting") is declared in a header file and defined
-outside of any function.  This means it can be accessed by any function
-within the user library.  For convenience, the definition is in the
-load_unload.cc file.
-- "load" is called with a LibraryHandle argument, this being used in
-the registration of functions.  As no functions are being registered
-in this example, the argument specification omits the variable name
-(whilst retaining the type) to avoid an "unused variable" compiler
-warning. (The LibraryHandle and its use is discussed in the section
- at ref hooksdgLibraryHandle.)
-- In the current version of the hooks framework, it is not possible to pass
-any configuration information to the "load" function.  The name of the log
-file must therefore be hard-coded as an absolute path name or communicated
-to the user code by some other means.
-- "load" must 0 on success and non-zero on error.  The hooks framework
-will abandon the loading of the library if "load" returns an error status.
-(In this example, "interesting" can be tested as a boolean value,
-returning "true" if the file opened successfully.)
-- "unload" closes the log file if it is open and is a no-op otherwise. As
-with "load", a zero value must be returned on success and a non-zero value
-on an error.  The hooks framework will record a non-zero status return
-as an error in the current BIND 10 log but otherwise ignore it.
-- As before, the function definitions are enclosed in 'extern "C"' braces.
-
- at subsection hooksdgCallouts Callouts
-
-Having sorted out the framework, we now come to the functions that
-actually do something.  These functions are known as "callouts" because
-the BIND 10 code "calls out" to them.  Each BIND 10 server has a number of
-hooks to which callouts can be attached: server-specific documentation
-describes in detail the points in the server at which the hooks are
-present together with the data passed to callouts attached to them.
-
-Before we continue with the example, we'll discuss how arguments are
-passed to callouts and information is returned to the server.  We will
-also discuss how information can be moved between callouts.
-
- at subsubsection hooksdgCalloutSignature The Callout Signature
-
-All callouts are declared with the signature:
- at code
-extern "C" {
-int callout(CalloutHandle& handle);
-};
- at endcode
-
-(As before, the callout is declared with "C" linkage.)  Information is passed
-between BIND 10 and the callout through name/value pairs in the CalloutHandle
-object. The object is also used to pass information between callouts on a
-per-request basis. (Both of these concepts are explained below.)
-
-A callout returns an "int" as a status return.  A value of 0 indicates
-success, anything else signifies an error.  The status return has no
-effect on server processing; the only difference between a success
-and error code is that if the latter is returned, the server will
-log an error, specifying both the library and hook that generated it.
-Effectively the return status provides a quick way for a callout to log
-error information to the BIND 10 logging system.
-
- at subsubsection hooksdgArguments Callout Arguments
-
-The CalloutHandle object provides two methods to get and set the
-arguments passed to the callout.  These methods are called (naturally
-enough) getArgument and SetArgument.  Their usage is illustrated by the
-following code snippets.
-
- at code
-    // Server-side code snippet to show the setting of arguments
-
-    int count = 10;
-    boost::shared_ptr<Pkt4> pktptr = ... // Set to appropriate value
-
-    // Assume that "handle" has been created
-    handle.setArgument("data_count", count);
-    handle.setArgument("inpacket", pktptr);
-
-    // Call the callouts attached to the hook
-    ...
-
-    // Retrieve the modified values
-    handle.getArgument("data_count", count);
-    handle.getArgument("inpacket", pktptr);
- at endcode
-
-In the callout
-
- at code
-    int number;
-    boost::shared_ptr<Pkt4> packet;
-
-    // Retrieve data set by the server.
-    handle.getArgument("data_count", number);
-    handle.getArgument("inpacket", packet);
-
-    // Modify "number"
-    number = ...;
-
-    // Update the arguments to send the value back to the server.
-    handle.setArgument("data_count", number);
- at endcode
-
-As can be seen "getArgument" is used to retrieve data from the
-CalloutHandle, and setArgument used to put data into it.  If a callout
-wishes to alter data and pass it back to the server, it should retrieve
-the data with getArgument, modify it, and call setArgument to send
-it back.
-
-There are several points to be aware of:
-
-- the data type of the variable in the call to getArgument must match
-the data type of the variable passed to the corresponding setArgument
-<B>exactly</B>: using what would normally be considered to be a
-"compatible" type is not enough.  For example, if the server passed
-an argument as an "int" and the callout attempted to retrieve it as a
-"long", an exception would be thrown even though any value that can
-be stored in an "int" will fit into a "long".  This restriction also
-applies the "const" attribute but only as applied to data pointed to by
-pointers, e.g. if an argument is defined as a "char*", an exception will
-be thrown if an attempt is made to retrieve it into a variable of type
-"const char*".  (However, if an argument is set as a "const int", it can
-be retrieved into an "int".)  The documentation of each hook point will
-detail the data type of each argument.
-- Although all arguments can be modified, some altered values may not
-be read by the server. (These would be ones that the server considers
-"read-only".) Consult the documentation of each hook to see whether an
-argument can be used to transfer data back to the server.
-- If a pointer to an object is passed to a callout (either a "raw"
-pointer, or a boost smart pointer (as in the example above), and the
-underlying object is altered through that pointer, the change will be
-reflected in the server even if no call is made to setArgument.
-
-In all cases, consult the documentation for the particular hook to see whether
-parameters can be modified.  As a general rule:
-
-- Do not alter arguments unless you mean the change to be reflected in
-the server.
-- If you alter an argument, call CalloutHandle::setArgument to update the
-value in the CalloutHandle object.
-
- at subsubsection hooksdgSkipFlag The "Skip" Flag
-
-When a to callouts attached to a hook returns, the server will usually continue
-its processing.  However, a callout might have done something that means that
-the server should follow another path.  Possible actions a server could take
-include:
-
-- Skip the next stage of processing because the callout has already
-done it.  For example, a hook is located just before the DHCP server
-allocates an address to the client.  A callout may decide to allocate
-special addresses for certain clients, in which case it needs to tell
-the server not to allocate an address in this case.
-- Drop the packet and continue with the next request. A possible scenario
-is a DNS server where a callout inspects the source address of an incoming
-packet and compares it against a black list; if the address is on it,
-the callout notifies the server to drop the packet.
-
-To handle these common cases, the CalloutHandle has a "skip" flag.
-This is set by a callout when it wishes the server to skip normal
-processing.  It is set false by the hooks framework before callouts on a
-hook are called.  If the flag is set on return, the server will take the
-"skip" action relevant for the hook.
-
-The methods to get and set the "skip" flag are getSkip and setSkip. Their
-usage is intuitive:
-
- at code
-    // Get the current setting of the skip flag.
-    bool skip = handle.getSkip();
-
-    // Do some processing...
-        :
-    if (lease_allocated) {
-        // Flag the server to skip the next step of the processing as we
-        // already have an address.
-        handle.setSkip(true);
-    }
-    return;
-    
- at endcode
-
-Like arguments, the "skip" flag is passed to all callouts on a hook.  Callouts
-later in the list are able to examine (and modify) the settings of earlier ones.
-
- at subsubsection hooksdgCalloutContext Per-Request Context
-
-Although many of the BIND 10 modules can be characterised as handling
-singles packet - e.g. the DHCPv4 server receives a DISCOVER packet,
-processes it and responds with an OFFER, this is not true in all cases.
-The principal exception is the recursive DNS resolver: this receives a
-packet from a client but that packet may itself generate multiple packets
-being sent to upstream servers. To avoid possible confusion the rest of
-this section uses the term "request" to indicate a request by a client
-for some information or action.
-
-As well as argument information, the CalloutHandle object can be used by
-callouts to attach information to a request being handled by the server.
-This information (known as "context") is not used by the server: its purpose
-is to allow callouts to pass information between one another on a
-per-request basis.
-
-Context only exists only for the duration of the request: when a request
-is completed, the context is destroyed.  A new request starts with no
-context information.  Context is particularly useful in servers that may
-be processing multiple requests simultaneously: callouts can effectively
-attach data to a request that follows the request around the system.
-
-Context information is held as name/value pairs in the same way
-as arguments, being accessed by the pair of methods setContext and
-getContext.  They have the same restrictions as the setArgument and
-getArgument methods - the type of data retrieved from context must
-<B>exactly</B> match the type of the data set.
-
-The example in the next section illustrates their use.
-
- at subsection hooksdgExampleCallouts Example Callouts
-
-Continuing with the tutorial, the requirements need us to retrieve the
-hardware address of the incoming packet, classify it, and write it,
-together with the assigned IP address, to a log file.  Although we could
-do this in one callout, for this example we'll use two:
-
-- pkt_rcvd - a callout on this hook is invoked when a packet has been
-received and has been parsed.  It is passed a single argument, "query"
-which is an isc::dhcp::Pkt4 object (representing a DHCP v4 packet).
-We will do the classification here.
-
-- v4_lease_write_post - called when the lease (an assignment of an IPv4
-address to a client for a fixed period of time) has been written to the
-database. It is passed two arguments, the query ("query")
-and the response (called "reply").  This is the point at which the
-example code will write the hardware and IP addresses to the log file.
-
-The standard for naming callouts is to give them the same name as
-the hook.  If this is done, the callouts will be automatically found
-by the Hooks system (this is discussed further in section @ref
-hooksdgCalloutRegistration).  For our example, we will assume this is the
-case, so the code for the first callout (used to classify the client's
-hardware address) is:
-
- at code
-// pkt_rcvd.cc
-
-#include <hooks/hooks.h>
-#include <dhcp/pkt4.h>
-#include "library_common.h"
-
-#include <string>
-
-using namespace isc::dhcp;
-using namespace std;
-
-extern "C" {
-
-// This callout is called at the "pkt_rcvd" hook.
-int pkt_rcvd(CalloutHandle& handle) {
-
-    // A pointer to the packet is passed to the callout via a "boost" smart
-    // pointer. The include file "pkt4.h" typedefs a pointer to the Pkt4
-    // object as Pkt4Ptr.  Retrieve a pointer to the object.
-    Pkt4Ptr query_ptr;
-    handle.getArgument("query", query_ptr);
-
-    // Point to the hardware address.
-    HwAddrPtr hwaddr_ptr = query_ptr->getHWAddr();
-
-    // The hardware address is held in a public member variable. We'll classify
-    // it as interesting if the sum of all the bytes in it is divisible by 4.
-    //  (This is a contrived example after all!)
-    long sum = 0;
-    for (int i = 0; i < hwaddr_ptr->hwaddr_.size(); ++i) {
-        sum += hwaddr_ptr->hwadr_[i];
-    }
-
-    // Classify it.
-    if (sum % 4 == 0) {
-        // Store the text form of the hardware address in the context to pass
-        // to the next callout.
-        handle.setContext("hwaddr", hwaddr_ptr->hwaddr_.toText());
-    }
-
-    return (0);
-};
- at endcode
-
-The pct_rcvd callout placed the hardware address of an interesting client in
-the "hwaddr" context for the packet.  Turning now to the callout that will
-write this information to the log file:
-
- at code
-// v4_lease_write.cc
-
-#include <hooks/hooks.h>
-#include <dhcp/pkt4.h>
-#include "library_common.h"
-
-#include <string>
-
-using namespace isc::dhcp;
-using namespace std;
-
-extern "C" {
-
-// This callout is called at the "v4_lease_write_post" hook.
-int v4_lease_write_post(CalloutHandle& handle) {
-
-    // Obtain the hardware address of the "interesting" client.  We have to
-    // use a try...catch block here because if the client was not interesting,
-    // no information would be set and getArgument would thrown an exception.
-    string hwaddr;
-    try (handle.getArgument("hwaddr", hwaddr) {
-
-        // getArgument didn't throw so the client is interesting.  Get a pointer
-        // to the reply.  Note that the argument list for this hook also
-        // contains a pointer to the query: we don't need to access that in this
-        // example.
-        Pkt4Ptr reply;
-        handle.getArgument("reply", reply);
-
-        // Get the string form of the IP address.
-        string ipaddr = reply->getYiaddr().toText();
-
-        // Write the information to the log file.
-        interesting << hwaddr << " " << ipaddr << "\n";
-
-        // ... and to guard against a crash, we'll flush the output stream.
-        flush(interesting);
-
-    } catch (const NoSuchCalloutContext&) {
-
-        // No such element in the per-request context with the name
-        // "hwaddr".  We will do nothing, so just dismiss the exception.
-
-    }
-
-    return (0);
-}
-
-};
- at endcode
-
- at subsection hooksdgBuild Building the Library
-
-Building the code requires building a shareable library.  This requires
-the the code be compiled as positition-independent code (using the
-compiler's "-fpic" switch) and linked as a shared library (with the
-linker's "-shared" switch).  The build command also needs to point to
-the BIND 10 include directory and link in the appropriate libraries.
-
-Assuming that BIND 10 has been installed in the default location, the
-command line needed to create the library using the Gnu C++ compiler on a
-Linux system is:
-
- at code
-g++ -I /usr/include/bind10 -L /usr/lib/bind10 -fpic -shared -o example.so \
-    load_unload.cc pkt_rcvd.cc v4_lease_write.cc version.cc \
-    -lb10-dhcp++ -lb10-util -lb10-exceptions
- at endcode
-
-Notes:
-- The compilation command and switches required may vary depending on
-your operating system and compiler - consult the relevant documentation
-for details.
-- The values for the "-I" and "-L" switches depend on where you have
-installed BIND 10.
-- The list of libraries that need to be included in the command line
-depends on the functionality used by the hook code and the module to
-which they are attached (e.g. hook code for DNS will need to link against
-the libb10-dns++ library).  Depending on operating system, you may also need
-to explicitly list libraries on which the BIND 10 libraries depend.
-
- at subsection hooksdgConfiguration Configuring the Hook Library
-
-The final step is to make the library known to BIND 10.  All BIND 10 modules to
-which hooks can be added contain the "hook_library" element, and user
-libraries are added to this. (The BIND 10 hooks system can handle multiple libraries - this is discussed below.).
-
-To add the example library (assumed to be in /usr/local/lib) to the DHCPv4
-module, the following bindctl commands must be executed:
-
- at code
-> config add Dhcp4/hook_libraries
-> config set Dhcp4/hook_libraries[0] "/usr/local/lib/example.so"
-> config commit
- at endcode
-
-The DHCPv4 server will load the library and execute the callouts each time a
-request is received.
-
- at section hooksdgAdvancedTopics Advanced Topics
-
- at subsection hooksdgContextCreateDestroy Context Creation and Destruction
-
-As well as the hooks defined by the server, the hooks framework defines
-two hooks of its own, "context_create" and "context_destroy".  The first
-is called when a request is created in the server, before any of the
-server-specific hooks gets called.  It's purpose it to allow a library
-to initialize per-request context. The second is called after all
-server-defined hooks have been processed, and is to allow a library to
-tidy up.
-
-As an example, the v4_lease_write example above required that the code
-check for an exception being thrown when accessing the "hwaddr" context
-item in case it was not set.  An alternative strategy would have been to
-provide a callout for the "context_create" hook and set the context item
-"hwaddr" to an empty string. Instead of needing to handle an exception,
-v4_lease_write would be guaranteed to get something when looking for
-the hwaddr item and so could write or not write the output depending on
-the value.
-
-In most cases, "context_destroy" is not needed as the Hooks system
-automatically deletes context. An example where it could be required
-is where memory has been allocated by a callout during the processing
-of a request and a raw pointer to it stored in the context object. On
-destruction of the context, that memory will not be automatically
-released. Freeing in the memory in the "context_destroy callout will solve
-that problem.
-
-Actually, when the context is destroyed, the destructor
-associated with any objects stored in it are run. Rather than point to
-allocated memory with a raw pointer, a better idea would be to point to
-it with a boost "smart" pointer and store that pointer in the context.
-When the context is destroyed, the smart pointer's destructor is run,
-which will automatically delete the pointed-to object.
-
-These approaches are illustrated in the following examples.
-Here it is assumed that the hooks library is performing some form of
-security checking on the packet and needs to maintain information in
-a user-specified "SecurityInformation" object. (The details of this
-fictitious object are of no concern here.) The object is created in
-the context_create callout and used in both the pkt4_rcvd and the
-v4_lease_write_post callouts.
-
- at code
-// Storing information in a "raw" pointer.  Assume that the
-
-#include <hooks/hooks.h>
-   :
-
-extern "C" {
-
-// context_create callout - called when the request is created.
-int context_create(CalloutHandle& handle) {
-    // Create the security information and store it in the context
-    // for this packet.
-    SecurityInformation* si = new SecurityInformation();
-    handle.setContext("security_information", si);
-}
-
-// Callouts that use the context
-int pktv_rcvd(CalloutHandle& handle) {
-    // Retrieve the pointer to the SecurityInformation object
-    SecurityInformation si;
-    handle.getContext("security_information", si);
-        :
-        :
-    // Set the security information
-    si->setSomething(...);
-
-    // The pointed-to information has been updated but the pointer has not been
-    // altered, so there is no need to call setContext() again.
-}
-
-int v4_lease_write_post(CalloutHandle& handle) {
-    // Retrieve the pointer to the SecurityInformation object
-    SecurityInformation si;
-    handle.getContext("security_information", si);
-        :
-        :
-    // Retrieve security information
-    bool active = si->getSomething(...);
-        :
-}
-
-// Context destruction.  We need to delete the pointed-to SecurityInformation
-// object because we will lose the pointer to it when the CalloutHandle is
-// destroyed.
-int context_destroy(CalloutHandle& handle) {
-    // Retrieve the pointer to the SecurityInformation object
-    SecurityInformation si;
-    handle.getContext("security_information", si);
-
-    // Delete the pointed-to memory.
-    delete si;
-}
- at endcode
-
-The requirement for the context_destroy callout can be eliminated if
-a Boost shared ptr is used to point to the allocated memory:
-
- at code
-// Storing information in a "raw" pointer.  Assume that the
-
-#include <hooks/hooks.h>
-#include <boost/shared_ptr.hpp>
-   :
-
-extern "C" {
-
-// context_create callout - called when the request is created.
-
-int context_create(CalloutHandle& handle) {
-    // Create the security information and store it in the context for this
-    // packet.
-    boost::shared_ptr<SecurityInformation> si(new SecurityInformation());
-    handle.setContext("security_information", si);
-}
-
-// Other than the data type, a shared pointer has similar semantics to a "raw"
-// pointer.  Only the code from pkt_rcvd is shown here.
-
-int pktv_rcvd(CalloutHandle& handle) {
-    // Retrieve the pointer to the SecurityInformation object
-    boost::shared_ptr<SecurityInformation> si;
-    handle.setContext("security_information", si);
-        :
-        :
-    // Modify the security information
-    si->setSomething(...);
-
-    // The pointed-to information has been updated but the pointer has not
-    // altered, so theree is no need to reset the context.
-}
-
-// No context_destroy callout is needed to delete the allocated
-// SecurityInformation object.  When the CalloutHandle is destroyed, the shared
-// pointer object will be destroyed.  If that is the last shared pointer to the
-// allocated memory, then it too will be deleted.
- at endcode
-
-(Note that a Boost shared pointer - rather than any other Boost smart pointer -
-should be used, as the pointer objects are copied within the hooks framework and
-only shared pointers have the correct behavior for the copy operation.)
-
-
- at subsection hooksdgCalloutRegistration Registering Callouts
-
-As briefly mentioned in @ref hooksdgExampleCallouts, the standard is for
-callouts in the user library to have the same name as the name of the
-hook to which they are being attached.  This convention was followed
-in the tutorial, e.g.  the callout that needed to be attached to the
-"pkt_rcvd" hook was named pkt_rcvd.
-
-The reason for this convention is that when the library is loaded, the
-hook framework automatically searches the library for functions with
-the same names as the server hooks.  When it finds one, it attaches it
-to the appropriate hook point.  This simplifies the loading process and
-bookkeeping required to create a library of callouts.
-
-However, the hooks system is flexible in this area: callouts can have
-non-standard names, and multiple callouts can be registered on a hook.
-
- at subsubsection hooksdgLibraryHandle The LibraryHandle Object
-
-The way into the part of the hooks framework that allows callout
-registration is through the LibraryHandle object.  This was briefly
-introduced in the discussion of the framework functions, in that
-an object of this type is pass to the "load" function.  A LibraryHandle
-can also be obtained from within a callout by calling the CalloutHandle's
-getLibraryHandle() method.
-
-The LibraryHandle provides three methods to manipulate callouts:
-
-- registerCallout - register a callout on a hook.
-- deregisterCallout - deregister a callout from a hook.
-- deregisterAllCallouts - deregister all callouts on a hook.
-
-The following sections cover some of the ways in which these can be used.
-
- at subsubsection hooksdgNonstandardCalloutNames Non-Standard Callout Names
-
-The example in the tutorial used standard names for the callouts.  As noted
-above, it is possible to use non-standard names.  Suppose, instead of the
-callout names "pkt_rcvd" and "v4_lease_write", we had named our callouts
-"classify" and "write_data".  The hooks framework would not have registered
-these callouts, so we would have needed to do it ourself.  The place to
-do this is the "load" framework function, and its code would have had to
-been modified to:
-
- at code
-int load(LibraryHandle& libhandle) {
-    // Register the callouts on the hooks. We assume that a header file
-    // declares the "classify" and "write_data" functions.
-    libhandle.registerCallout("pkt_rcvd", classify);
-    libhandle.registerCallout("v4_lease_write", write_data);
-
-    // Open the log file
-    interesting.open("/data/clients/interesting.log",
-                     std::fstream::out | std::fstream::app);
-    return (interesting ? 0 : 1);
-}
- at endcode
-
-It is possible for a library to contain callouts with both standard and
-non-standard names: ones with standard names will be registered automatically,
-ones with non-standard names need to be registered manually.
-
- at subsubsection hooksdgMultipleCallouts Multiple Callouts on a Hook
-
-The BIND 10 hooks framework allows multiple callouts to be attached to 
-a hook point.  Although it is likely to be rare for user code to need to
-do this, there may be instances where it make sense.
-
-To register multiple callouts on a hook, just call
-LibraryHandle::registerCallout multiple times on the same hook, e.g.
-
- at code
-    libhandle.registerCallout("pkt_rcvd", classify);
-    libhandle.registerCallout("pkt_rcvd", write_data);
- at endcode
-
-The hooks framework will call the callouts in the order they are
-registered.  The same CalloutHandle is passed between them, so any
-change made to the CalloutHandle's arguments, "skip" flag, or per-request
-context by the first is visible to the second.
-
- at subsubsection hooksdgDynamicRegistration Dynamic Registration and Reregistration of Callouts
-
-The previous sections have dealt with callouts being registered during
-the call to "load".  The hooks framework is more flexible than that
-in that callouts can be registered and deregistered within a callout.
-In fact, a callout is able to register or deregister itself, and a callout
-is able to be registered on a hook multiple times.
-
-Using our contrived example again, the DHCPv4 server processes one request
-to completion before it starts processing the next.  With this knowledge,
-we could alter the logic of the code so that the callout attached to the
-"pkt_rcvd" hook registers the callout doing the logging when it detects
-an interesting packet, and the callout doing the logging deregisters
-itself in its execution.  The relevant modifications to the code in
-the tutorial are shown below:
-
- at code
-// pkt_rcvd.cc
-//      :
-
-int pkt_rcvd(CalloutHandle& handle) {
-
-            :
-            :
-
-    // Classify it.
-    if (sum % 4 == 0) {
-        // Store the text form of the hardware address in the context to pass
-        // to the next callout.
-        handle.setContext("hwaddr", hwaddr_ptr->hwaddr_.toText());
-
-        // Register the callback to log the data.
-        handle.getLibraryHandle().registerCallout("v4_lease_write", write_data);
-    }
-
-    return (0);
-};
- at endcode
-
- at code
-// v4_lease_write.cc
-        :
-
-int write_data(CalloutHandle& handle) {
-
-    // Obtain the hardware address of the "interesting" client. As the
-    // callback is only registered when interesting data is present, we
-    // know that the context contains the hardware address so an exception
-    // will not be thrown when we call getArgument().
-    string hwaddr;
-    handle.getArgument("hwaddr", hwaddr);
-
-    // The pointer to the reply.
-    ConstPkt4Ptr reply;
-    handle.getArgument("reply", reply);
-
-    // Get the string form of the IP address.
-    string ipaddr = reply->getYiaddr().toText():
-
-    // Write the information to the log file and flush.
-    interesting << hwaddr << " " << ipaddr << "\n";
-    flush(interesting);
-
-    // We've logged the data, so deregister ourself.  This callout will not
-    // be called again until it is registered by pkt_rcvd.
-
-    handle.getLibraryHandle().deregisterCallout("v4_lease_write", write_data);
-
-    return (0);
-}
- at endcode
-
-Note that the above example used a non-standard name for the callout
-that wrote the data.  Had the name been a standard one, it would have been
-registered when the library was loaded and called for the first request,
-regardless of whether that was defined as "interesting".  (Although as
-callouts with standard names are always registered before "load" gets called,
-we could have got round that problem by deregistering that particular
-callout in the "load" function.)
-
-
- at note Deregistration of a callout on the hook that is currently
-being called only takes effect when the server next calls the hook.
-To illustrate this, suppose the callouts attached to a hook are A, B and C
-(in that order), and during execution, A deregisters B and C and adds D.
-When callout A returns, B and C will still run.  The next time the server
-calls the hook's callouts, A and D will run (in that order).
-
- at subsection hooksdgMultipleLibraries Multiple User Libraries
-
-As alluded to in the section @ref hooksdgConfiguration, BIND 10 can load
-multiple libraries.  The libraries are loaded in the order specified in
-the configuration, and the callouts attached to the hooks in the order
-presented by the libraries.
-
-The following picture illustrates this, and also illustrates the scope of
-data passed around the system.
-
- at image html DataScopeArgument.png "Scope of Arguments"
-
-In this illustration, a server has three hook points, alpha, beta
-and gamma.  Two libraries are configured, library 1 and library 2.
-Library 1 registers the callout "authorize" for hook alpha, "check" for
-hook beta and "add_option" for hook gamma.  Library 2 registers "logpkt",
-"validate" and "putopt"
-
-The horizontal red lines represent arguments to callouts.  When the server
-calls hook alpha, it creates an argument list and calls the
-first callout for the hook, "authorize".  When that callout returns, the
-same (but possibly modified) argument list is passed to the next callout
-in the chain, "logpkt".  Another, separate argument list is created for
-hook beta and passed to the callouts "check" and "validate" in
-that order.  A similar sequence occurs for hook gamma.
-
-The next picture shows the scope of the context associated with a
-request.
-
- at image html DataScopeContext.png "Illustration of per-library context"
-
-The vertical blue lines represent callout context. Context is
-per-packet but also per-library.  When the server calls "authorize",
-the CalloutHandle's getContext and setContext methods access a context
-created purely for library 1. The next callout on the hook will access
-context created for library 2. These contexts are passed to the callouts
-associated with the next hook.  So when "check" is called, it gets the
-context data that was set by "authorize", when "validate" is called,
-it gets the context data set by "logpkt".
-
-It is stressed that the context for callouts associated with different
-libraries is entirely separate.  For example, suppose "authorize" sets
-the CalloutHandle's context item "foo" to 2 and "logpkt" sets an item of
-the same name to the string "bar".  When "check" accesses the context
-item "foo", it gets a value of 2; when "validate" accesses an item of
-the same name, it gets the value "bar".
-
-It is also stressed that all this context exists only for the life of the
-request being processed.  When that request is complete, all the
-context associated with that request - for all libraries - is destroyed,
-and new context created for the next request.
-
-This structure means that library authors can use per-request context
-without worrying about the presence of other libraries.  Other libraries
-may be present, but will not affect the context values set by a library's
-callouts.
-
- at subsection hooksdgInterLibraryData Passing Data Between Libraries
-
-In rare cases, it is possible that one library may want to pass
-data to another.  This can be done in a limited way by means of the
-CalloutHandle's setArgument and getArgument calls.  For example, in the
-above diagram, the callout "add_option" can pass a value to "putopt"
-by setting a name.value pair in the hook's argument list.  "putopt"
-would be able to read this, but would not be able to return information
-back to "add_option".
-
-All argument names used by BIND 10 will be a combination of letters
-(both upper- and lower-case), digits, hyphens and underscores: no
-other characters will be used.  As argument names are simple strings,
-it is suggested that if such a mechanism be used, the names of the data
-values passed between the libraries include a special character such as
-the dollar symbol or percent sign.  In this way there is no danger that
-a name will conflict with any existing or future BIND 10 argument names.
-
-
- at subsection hooksdgRegisterMultipleLibraries Dynamic Callout Registration and Multiple Libraries
-
-On a particular hook, callouts are called in the order the libraries appear
-in the configuration and, within a library, in the order the callouts
-are registered.
-
-This order applies to dynamically-registered callouts as well.  As an
-example, consider the diagram above where for hook "beta", callout "check"
-is followed by callout "validate".  Suppose that when "authorize" is run,
-it registers a new callout ("double_check") on hook "beta".  That
-callout will be inserted at the end of the callouts registered by
-library 1 and before any registered by library 2.  It would therefore
-appear between "check" and "validate".  On the other hand, if it were
-"logpkt" that registered the new callout, "double_check" would appear
-after "validate".
-
-*/
diff --git a/src/lib/hooks/hooks_component_developer.dox b/src/lib/hooks/hooks_component_developer.dox
index edf59a8..777ae2e 100644
--- a/src/lib/hooks/hooks_component_developer.dox
+++ b/src/lib/hooks/hooks_component_developer.dox
@@ -31,7 +31,7 @@ BIND 10 component to use hooks.  It shows how the component should be written
 to load a shared library at run-time and how to call functions in it.
 
 For information about writing a hooks library containing functions called by BIND 10
-during its execution, see the document @ref hooksDevelopersGuide.
+during its execution, see the document @ref hooksdgDevelopersGuide.
 
 @subsection hooksComponentTerminology Terminology
 
@@ -53,7 +53,7 @@ to execute a user-written function.
 shared library and loaded by BIND 10 into its address space.  Multiple
 user libraries can be loaded at the same time, each containing callouts for
 the same hooks.  The hooks framework calls these libraries one after the
-other. (See the document @ref hooksDevelopersGuide for more details.)
+other. (See the document @ref hooksdgDevelopersGuide for more details.)
 
 @subsection hooksComponentLanguages Languages
 
@@ -463,7 +463,7 @@ It is possible for a component to register its own functions (i.e. within
 its own address space) as hook callouts.  These functions are called
 in eactly the same way as user callouts, being passed their arguments
 though a CalloutHandle object.  (Guidelines for writing callouts can be
-found in @ref hooksDevelopersGuide.)
+found in @ref hooksdgDevelopersGuide.)
 
 A component can associate with a hook callouts that run either before
 user-registered callouts or after them.  Registration is done via a
@@ -473,7 +473,7 @@ through the methods isc::hooks::HooksManager::preCalloutLibraryHandle()
 callouts) or isc::hooks::HooksManager::postCalloutLibraryHandle() (for
 a handle to register callouts to run after the user callouts).  Use of
 the LibraryHandle to register and deregister callouts is described in
- at ref hooksLibraryHandle.
+ at ref hooksdgLibraryHandle.
 
 Finally, it should be noted that callouts registered in this way only
 remain registered until the next call to isc::hooks::loadLibraries().
diff --git a/src/lib/hooks/hooks_maintenance.dox b/src/lib/hooks/hooks_maintenance.dox
new file mode 100644
index 0000000..6dd5deb
--- /dev/null
+++ b/src/lib/hooks/hooks_maintenance.dox
@@ -0,0 +1,270 @@
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// Note: the prefix "hooksmg" to all labels is an abbreviation for "Hooks
+// Maintenance Guide" and is used to prevent a clash with symbols in any
+// other Doxygen file.
+
+/**
+ @page hooksmgMaintenanceGuide Hooks Maintenance Guide
+
+ @section hooksmgIntroduction Introduction
+
+ This document is aimed at BIND 10 maintainers responsible for the hooks
+ system.  It provides an overview of the classes that make up the hooks
+ framework and notes important aspects of processing.  More detailed
+ information can be found in the source code.
+
+ It is assumed that the reader is familiar with the contents of the @ref
+ hooksdgDevelopersGuide and the @ref hooksComponentDeveloperGuide.
+
+ @section hooksmgObjects Hooks Framework Objects
+
+ The relationships betweeh the various objects in the hooks framework
+ is shown below:
+
+ @image html HooksUml.png "High-Level Class Diagram of the Hooks Framework"
+
+ (To avoid clutter, the @ref hooksmgServerHooks object, used to pass
+ information about registered hooks to the components, is not shown on
+ the diagram.)
+
+ The hooks framework objects can be split into user-side objects and
+ server-side objects.  The former are those objects used or referenced
+ by user-written hooks libraries.  The latter are those objects used in
+ the hooks framework.
+
+ @subsection hooksmgUserObjects User-Side Objects
+
+ The user-side code is able to access two objects in the framework,
+ the @ref hooksmgCalloutHandle and the @ref hooksmgLibraryHandle.
+ The @ref hooksmgCalloutHandle is used to pass data between the BIND 10
+ component and the loaded library; the @ref hooksmgLibraryHandle is used
+ for registering callouts.
+
+ @subsubsection hooksmgCalloutHandle Callout Handle
+
+ The @ref isc::hooks::CalloutHandle has two functions: passing arguments
+ between the BIND 10 component and the user-written library, and storing
+ per-request context between library calls.  In both cases the data is
+ stored in a std::map structure, keyed by argument (or context item) name.
+ The actual data is stored in a boost::any object, which allows any
+ data type to be stored, although a penalty for this flexibility is
+ the restriction (mentioned in the @ref hooksdgDevelopersGuide) that
+ the type of data retrieved must be identical (and not just compatible)
+ with that stored.
+
+ The storage of context data is slightly complex because there is
+ separate context for each user library.  For this reason, the @ref
+ hooksmgCalloutHandle has multiple maps, one for each library loaded.
+ The maps are stored in another map, the appropriate map being identified
+ by the "current library index" (this index is explained further below).
+ The reason for the second map (rather than a structure such as a vector)
+ is to avoid creating individual context maps unless needed; given the
+ key to the map (in this case the current library index) accessing an
+ element in a map using the operator[] method returns the element in
+ question if it exists, or creates a new one (and stores it in the map)
+ if its doesn't.
+
+ @subsubsection hooksmgLibraryHandle Library Handle
+
+ Little more than a restricted interface to the @ref
+ hooksmgCalloutManager, the @ref isc::hooks::LibraryHandle allows a
+ callout to register and deregister callouts.  However, there are some
+ quirks to callout registration which, although the processing involved
+ is in the @ref hooksmgCalloutManager, are best described here.
+
+ Firstly, a callout can be deregistered by a function within a user
+ library only if it was registered by a function within that library. That
+ is to say, if library A registers the callout A_func() on hook "alpha"
+ and library B registers B_func(), functions within library A are only
+ able to remove A_func() (and functions in library B remove B_func()).
+ The restriction - here to prevent one library interfering with the
+ callouts of another - is enforced by means of the current library index.
+ As described below, each entry in the vector of callouts associated with
+ a hook is a pair object, comprising a pointer to the callout and
+ the index of the library with which it is associated. A callout
+ can only modify entries in that vector where the current library index
+ matches the index element of the pair.
+
+ A second quirk is that when dynamically modifying the list of callouts,
+ the change only takes effect when the current call out from the server
+ completes. To clarify this, suppose that functions A_func(), B_func()
+ and C_func() are registered on a hook, and the server executes a callout
+ on the hook. Suppose also during this call, A_func() removes the callout
+ C_func() and that B_func() adds D_func(). As changes only take effect
+ when the current call out completes, the user callouts executed will be
+ A_func(), B_func() then C_func(). When the server calls the hook callouts
+ again, the functions executed will be A_func(), B_func() and D_func().
+
+ This restriction is down to implementation.  When a set of callouts on a hook
+ is being called, the @ref hooksmgCalloutManager iterates through a
+ vector (the "callout vector") of (index, callout pointer) pairs.  Since
+ registration or deregistration of a callout on that hook would change the
+ vector (and so potentially invalidate the iterators used to access the it),
+ a copy of the vector is taken before the iteration starts.  The @ref
+ hooksmgCalloutManager iterates over this copy while any changes made
+ by the callout registration functions affect the relevant callout vector.
+
+ @subsection hooksmgServerObjects Server-Side Objects
+
+ @subsubsection hooksmgServerHooks Server Hooks
+
+ The singleton @ref isc::hooks::ServerHooks object is used to register
+ hooks. It is little more than a wrapper around a map of (hook index,
+ hook name), generating a unique number (the hook index) for each
+ hook registered.  It also handles the registration of the pre-defined
+ context_create and context_destroy hooks.
+
+ In operation, the @ref hooksmgHooksManager provides a thin wrapper
+ around it, so that the BIND 10 component developer does not have to
+ worry about another object.
+
+ @subsubsection hooksmgLibraryManager Library Manager
+
+ An @ref isc::hooks::LibraryManager is created by the @ref
+ hooksmgHooksManager object for each shared library loaded. It
+ controls the loading and unloading of the library and in essence
+ represents the library in the hooks framework. It also handles the
+ registration of the standard callouts (functions in the library with
+ the same name as the hook name).
+
+ Of particular importance is the "library's index", a number associated
+ with the library.  This is passed to the LibraryManager at creation
+ time and is used to tag the callout pointers.  It is discussed
+ further below.
+
+ As the LibraryManager provides all the methods needed to manage the
+ shared library, it is the natural home for the static validateLibrary()
+ method. The function called the parsing of the BIND 10 configuration, when
+ the "hooks-libraries" element is processed. It checks that shared library
+ exists, that it can be opened, that it contains the "version()" function
+ and that that function returns a valid value. It then closes the shared
+ library and returns an appropriate indication as to the library status.
+
+ @subsubsection hooksmgLibraryManagerCollection Library Manager Collection
+
+ The hooks framework can handle multiple libraries and as
+ a result will create a @ref hooksmgLibraryManager for each
+ of them. The collection of LibraryManagers is managed by the
+ @ref isc::hooks::LibraryManagerCollection object which, in most
+ cases has a method corresponding to a @ref hooksmgLibraryManager
+ method, e.g. it has a loadLibraries() that corresponds to the @ref
+ hooksmgLibraryManager's loadLibrary() call. As would be expected, methods
+ on the LibraryManagerCollection iterate through all specified libraries,
+ calling the corresponding LibraryManager method for each library.
+
+ One point of note is that LibraryManagerCollection operates on an "all
+ or none" principle. When loadLibraries() is called, on exit either all
+ libraries have been successfully opened or none of them have. There
+ is no use-case in BIND 10 where, after a user has specified the shared
+ libraries they want to load, the system will operate with only some of
+ them loaded.
+
+ The LibraryManagerCollection is the place where each library's index is set.
+ Each library is assigned a number ranging from 1 through to the number
+ of libraries being loaded.  As mentioned in the previous section, this
+ index is used to tag callout pointers, something that is discussed
+ in the next section.
+
+ (Whilst on the subject of library index numbers, two additional
+ numbers - 0 and INT_MAX - are also valid as "current library index".
+ For flexibility, the BIND 10 component is able to register its own
+ functions as hook callouts.  It does this by obtaining a suitable @ref
+ hooksmgLibraryHandle from the @ref hooksmgHooksManager.  A choice
+ of two is available: one @ref hooksmgLibraryHandle (with an index
+ of 0) can be used to register a callout on a hook to execute before
+ any user-supplied callouts.  The second (with an index of INT_MAX)
+ is used to register a callout to run after user-specified callouts.
+ Apart from the index number, the hooks framework does not treat these
+ callouts any differently from user-supplied ones.)
+
+ @subsubsection hooksmgCalloutManager Callout Manager
+
+ The @ref isc::hooks::CalloutManager is the core of the framework insofar
+ as the registration and calling of callouts is concerned.
+
+ It maintains a "hook vector - a vector with one element for
+ each registered hook. Each element in this vector is itself a
+ vector (the callout vector), each element of which is a pair of
+ (library index, callback pointer). When a callout is registered, the
+ CalloutManager's current library index is used to supply the "library
+ index" part of the pair. The library index is set explicitly by the
+ @ref hooksmgLibraryManager prior to calling the user library's load()
+ function (and prior to registering the standard callbacks).
+
+ The situation is slightly more complex when a callout is executing. In
+ order to execute a callout, the CalloutManager's callCallouts()
+ method must be called. This iterates through the callout vector for
+ a hook and for each element in the vector, uses the "library index"
+ part of the pair to set the "current library index" before calling the
+ callout function recorded in the second part of the pair. In most cases,
+ the setting of the library index has no effect on the callout. However,
+ if the callout wishes to dynamically register or deregister a callout,
+ the @ref hooksmgLibraryHandle (see above) calls a method on the
+ @ref hooksmgCalloutManager which in turn uses that information.
+
+ @subsubsection hooksmgHooksManager Hooks Manager
+
+ The @ref isc::hooks::HooksManager is the main object insofar as the
+ server is concerned. It controls the creation of the library-related
+ objects and provides the framework in which they interact. It also
+ provides a shell around objects such as @ref hooksmgServerHooks so that all
+ interaction with the hooks framework by the server is through the
+ HooksManager object.  Apart from this, it supplies no functionality to
+ the hooks framework.
+
+ @section hooksmgOtherIssues Other Issues
+
+ @subsection hooksmgMemoryAllocation Memory Allocation
+
+ Unloading a shared library works by unmapping the part of the process's
+ virtual address space in which the library lies. This may lead to
+ problems if there are still references to that address space elsewhere
+ in the process.
+
+ In many operating systems, heap storage allowed by a shared library
+ will lie in the virtual address allocated to the library. This has
+ implications in the hooks framework because:
+
+ - Argument information stored in a @ref hooksmgCalloutHandle by a
+ callout in a library may lie in the library's address space.
+
+ - Data modified in objects passed as arguments may lie in the address
+ space. For example, it is common for a DHCP callout to add "options"
+ to a packet: the memory allocated for those options will most likely
+ lie in library address space.
+
+ The problem really arises because of the extensive use by BIND 10 of
+ boost smart pointers. When the pointer is destroyed, the pointed-to
+ memory is deallocated. If the pointer points to address space that is
+ unmapped because a library has been unloaded, the deletion causes a
+ segmentation fault.
+
+ The hooks framework addresses the issue for the @ref hooksmgCalloutHandle
+ by keeping in that object a shared pointer to the object controlling
+ library unloading (the @ref hooksmgLibraryManagerCollection). Although
+ the libraries can be unloaded at any time, it is only when every
+ @ref hooksmgCalloutHandle that could possibly reference address space in the
+ library have been deleted that the library will actually be unloaded
+ and the address space unmapped.
+
+ The hooks framework cannot solve the second issue as the objects in
+ question are under control of the BIND 10 server incorporating the
+ hooks. It is up to the server developer to ensure that all such objects
+ have been destroyed before libraries are reloaded. In extreme cases
+ this may mean the server suspending all processing of incoming requests
+ until all currently executing requests have completed and data object
+ destroyed, reloading the libraries, then resuming processing.
+*/
diff --git a/src/lib/hooks/hooks_user.dox b/src/lib/hooks/hooks_user.dox
new file mode 100644
index 0000000..8aa75c1
--- /dev/null
+++ b/src/lib/hooks/hooks_user.dox
@@ -0,0 +1,1031 @@
+// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// Note: the prefix "hooksdg" to all labels is an abbreviation for "Hooks
+// Developer's Guide" and is used to prevent a clash with symbols in any
+// other Doxygen file.
+
+/**
+ @page hooksdgDevelopersGuide Hooks Developer's Guide
+
+ @section hooksdgIntroduction Introduction
+
+Although the BIND 10 framework and its associated DNS and DHCP programs
+provide comprehensive functionality, there will be times when it does
+not quite do what you require: the processing has to be extended in some
+way to solve your problem.
+
+Since the BIND 10 source code is freely available (BIND 10 being an
+open-source project), one option is to modify it to do what
+you want.  Whilst perfectly feasible, there are drawbacks:
+
+- Although well-documented, BIND 10 is a large program.  Just
+understanding how it works will take a significant amount of time. In
+addition, despite the fact that its object-oriented design keeps the
+coupling between modules to a minimum, an inappropriate change to one
+part of the program during the extension could cause another to
+behave oddly or to stop working altogether.
+
+- The change may need to be re-applied or re-written with every new
+version of BIND 10.  As new functionality is added or bugs are fixed,
+the code or algorithms in the core software may change - and may change
+significantly.
+
+To overcome these problems, BIND 10 provides the "Hooks" interface -
+a defined interface for third-party or user-written code. (For ease of
+reference in the rest of this document, all such code will be referred
+to as "user code".)  At specific points in its processing
+("hook points") BIND 10 will make a call to this code.  The call passes
+data that the user code can examine and, if required, modify.
+BIND 10 uses the modified data in the remainder of its processing.
+
+In order to minimise the interaction between BIND 10 and the user
+code, the latter is built independently of BIND 10 in the form of
+a shared library (or libraries).  These are made known to BIND 10
+through its configuration mechanism, and BIND 10 loads the library at
+run time. Libraries can be unloaded and reloaded as needed while BIND
+10 is running.
+
+Use of a defined API and the BIND 10 configuration mechanism means that
+as new versions of BIND 10 are released, there is no need to modify
+the user code.  Unless there is a major change in an interface
+(which will be clearly documented), all that will be required is a rebuild
+of the libraries.
+
+ at note Although the defined interface should not change, the internals
+of some of the classes and structures referenced by the user code may
+change between versions of BIND 10.  These changes have to be reflected
+in the compiled version of the software, hence the need for a rebuild.
+
+ at subsection hooksdgLanguages Languages
+
+The core of BIND 10 is written in C++.  While it is the intention to
+provide interfaces into user code written in other languages, the initial
+versions of the Hooks system requires that user code be written in C++.
+All examples in this guide are in that language.
+
+ at subsection hooksdgTerminology Terminology
+
+In the remainder of this guide, the following terminology is used:
+
+- Hook/Hook Point - used interchageably, this is a point in the code at
+which a call to user functions is made. Each hook has a name and
+each hook can have any number (including 0) of user functions
+attached to it.
+
+- Callout - a user function called by the server at a hook
+point. This is so-named because the server "calls out" to the library
+to execute a user function.
+
+- Framework function - the functions that a user library needs to
+supply in order for the hooks framework to load and unload the library.
+
+- User code/user library - non-BIND 10 code that is compiled into a
+shared library and loaded by BIND 10 into its address space.
+
+
+ at section hooksdgTutorial Tutorial
+
+To illustrate how to write code that integrates with BIND 10, we will
+use the following (rather contrived) example:
+
+The BIND 10 DHCPv4 server is used to allocate IPv4 addresses to clients
+(as well as to pass them other information such as the address of DNS
+servers).  We will suppose that we need to classify clients requesting
+IPv4 addresses according to their hardware address, and want to log both
+the hardware address and allocated IP address for the clients of interest.
+
+The following sections describe how to implement these requirements.
+The code presented here is not efficient and there are better ways of
+doing the task.  The aim however, is to illustrate the main features of
+user hook code not to provide an optimal solution.
+
+
+ at subsection hooksdgFrameworkFunctions Framework Functions
+
+Loading and initializing a library holding user code makes use
+of three (user-supplied) functions:
+
+- version - defines the version of BIND 10 code with which the user-library
+is built
+- load - called when the library is loaded by the server.
+- unload - called when the library is unloaded by the server.
+
+Of these, only "version" is mandatory, although in our example, all three
+are used.
+
+ at subsubsection hooksdgVersionFunction The "version" Function
+
+"version" is used by the hooks framework to check that the libraries
+it is loading are compatible with the version of BIND 10 being run.
+Although the hooks system allows BIND 10 and user code to interface
+through a defined API, the relationship is somewhat tight in that the
+user code will depend on the internal structures of BIND 10.  If these
+change - as they can between BIND 10 releases - and BIND 10 is run with
+a version of user code built against an earlier version of BIND
+10, a program crash could result.
+
+To guard against this, the "version" function must be provided in every
+library.  It returns a constant defined in header files of the version
+of BIND 10 against which it was built.  The hooks framework checks this
+for compatibility with the running version of BIND 10 before loading
+the library.
+
+In this tutorial, we'll put "version" in its own file, version.cc.  The
+contents are:
+
+ at code
+// version.cc
+
+#include <hooks/hooks.h>
+
+extern "C" {
+
+int version() {
+    return (BIND10_HOOKS_VERSION);
+}
+
+};
+ at endcode
+
+The file "hooks/hooks.h" is specified relative to the BIND 10 libraries
+source directory - this is covered later in the section @ref hooksdgBuild.
+It defines the symbol BIND10_HOOKS_VERSION, which has a value that changes
+on every release of BIND 10: this is the value that needs to be returned
+to the hooks framework.
+
+A final point to note is that the definition of "version" is enclosed
+within 'extern "C"' braces.  All functions accessed by the hooks
+framework use C linkage, mainly to avoid the name mangling that
+accompanies use of the C++ compiler, but also to avoid issues related
+to namespaces.
+
+ at subsubsection hooksdgLoadUnloadFunctions The "load" and "unload" Functions
+
+As the names suggest, "load" is called when a library is loaded and
+"unload" called when it is unloaded.  (It is always guaranteed that
+"load" is called: "unload" may not be called in some circumstances,
+e.g. if the system shuts down abnormally.)  These functions are the
+places where any library-wide resources are allocated and deallocated.
+"load" is also the place where any callouts with non-standard names
+(names that are not hook point names) can be registered:
+this is covered further in the section @ref hooksdgCalloutRegistration.
+
+The example does not make any use callouts with non-standard names.  However,
+as our design requires that the log file be open while BIND 10 is active
+and the library loaded, we'll open the file in the "load" function and close
+it in "unload".
+
+We create two files, one for the file handle declaration:
+
+ at code
+// library_common.h
+
+#ifndef LIBRARY_COMMON_H
+#define LIBRARY_COMMON_H
+
+#include <fstream>
+
+// "Interesting clients" log file handle declaration.
+extern std::fstream interesting;
+
+#endif // LIBRARY_COMMON_H
+ at endcode
+
+... and one to hold the "load" and "unload" functions:
+
+ at code
+// load_unload.cc
+
+#include <hooks/hooks.h>
+#include "library_common.h"
+
+// "Interesting clients" log file handle definition.
+std::fstream interesting;
+
+extern "C" {
+
+int load(LibraryHandle&) {
+    interesting.open("/data/clients/interesting.log",
+                     std::fstream::out | std::fstream::app);
+    return (interesting ? 0 : 1);
+}
+
+int unload() {
+    if (interesting) {
+        interesting.close();
+    }
+    return (0);
+}
+
+};
+ at endcode
+
+Notes:
+- The file handle ("interesting") is declared in a header file and defined
+outside of any function.  This means it can be accessed by any function
+within the user library.  For convenience, the definition is in the
+load_unload.cc file.
+- "load" is called with a LibraryHandle argument, this being used in
+the registration of functions.  As no functions are being registered
+in this example, the argument specification omits the variable name
+(whilst retaining the type) to avoid an "unused variable" compiler
+warning. (The LibraryHandle and its use is discussed in the section
+ at ref hooksdgLibraryHandle.)
+- In the current version of the hooks framework, it is not possible to pass
+any configuration information to the "load" function.  The name of the log
+file must therefore be hard-coded as an absolute path name or communicated
+to the user code by some other means.
+- "load" must 0 on success and non-zero on error.  The hooks framework
+will abandon the loading of the library if "load" returns an error status.
+(In this example, "interesting" can be tested as a boolean value,
+returning "true" if the file opened successfully.)
+- "unload" closes the log file if it is open and is a no-op otherwise. As
+with "load", a zero value must be returned on success and a non-zero value
+on an error.  The hooks framework will record a non-zero status return
+as an error in the current BIND 10 log but otherwise ignore it.
+- As before, the function definitions are enclosed in 'extern "C"' braces.
+
+ at subsection hooksdgCallouts Callouts
+
+Having sorted out the framework, we now come to the functions that
+actually do something.  These functions are known as "callouts" because
+the BIND 10 code "calls out" to them.  Each BIND 10 server has a number of
+hooks to which callouts can be attached: server-specific documentation
+describes in detail the points in the server at which the hooks are
+present together with the data passed to callouts attached to them.
+
+Before we continue with the example, we'll discuss how arguments are
+passed to callouts and information is returned to the server.  We will
+also discuss how information can be moved between callouts.
+
+ at subsubsection hooksdgCalloutSignature The Callout Signature
+
+All callouts are declared with the signature:
+ at code
+extern "C" {
+int callout(CalloutHandle& handle);
+};
+ at endcode
+
+(As before, the callout is declared with "C" linkage.)  Information is passed
+between BIND 10 and the callout through name/value pairs in the CalloutHandle
+object. The object is also used to pass information between callouts on a
+per-request basis. (Both of these concepts are explained below.)
+
+A callout returns an "int" as a status return.  A value of 0 indicates
+success, anything else signifies an error.  The status return has no
+effect on server processing; the only difference between a success
+and error code is that if the latter is returned, the server will
+log an error, specifying both the library and hook that generated it.
+Effectively the return status provides a quick way for a callout to log
+error information to the BIND 10 logging system.
+
+ at subsubsection hooksdgArguments Callout Arguments
+
+The CalloutHandle object provides two methods to get and set the
+arguments passed to the callout.  These methods are called (naturally
+enough) getArgument and SetArgument.  Their usage is illustrated by the
+following code snippets.
+
+ at code
+    // Server-side code snippet to show the setting of arguments
+
+    int count = 10;
+    boost::shared_ptr<Pkt4> pktptr = ... // Set to appropriate value
+
+    // Assume that "handle" has been created
+    handle.setArgument("data_count", count);
+    handle.setArgument("inpacket", pktptr);
+
+    // Call the callouts attached to the hook
+    ...
+
+    // Retrieve the modified values
+    handle.getArgument("data_count", count);
+    handle.getArgument("inpacket", pktptr);
+ at endcode
+
+In the callout
+
+ at code
+    int number;
+    boost::shared_ptr<Pkt4> packet;
+
+    // Retrieve data set by the server.
+    handle.getArgument("data_count", number);
+    handle.getArgument("inpacket", packet);
+
+    // Modify "number"
+    number = ...;
+
+    // Update the arguments to send the value back to the server.
+    handle.setArgument("data_count", number);
+ at endcode
+
+As can be seen "getArgument" is used to retrieve data from the
+CalloutHandle, and setArgument used to put data into it.  If a callout
+wishes to alter data and pass it back to the server, it should retrieve
+the data with getArgument, modify it, and call setArgument to send
+it back.
+
+There are several points to be aware of:
+
+- the data type of the variable in the call to getArgument must match
+the data type of the variable passed to the corresponding setArgument
+<B>exactly</B>: using what would normally be considered to be a
+"compatible" type is not enough.  For example, if the server passed
+an argument as an "int" and the callout attempted to retrieve it as a
+"long", an exception would be thrown even though any value that can
+be stored in an "int" will fit into a "long".  This restriction also
+applies the "const" attribute but only as applied to data pointed to by
+pointers, e.g. if an argument is defined as a "char*", an exception will
+be thrown if an attempt is made to retrieve it into a variable of type
+"const char*".  (However, if an argument is set as a "const int", it can
+be retrieved into an "int".)  The documentation of each hook point will
+detail the data type of each argument.
+- Although all arguments can be modified, some altered values may not
+be read by the server. (These would be ones that the server considers
+"read-only".) Consult the documentation of each hook to see whether an
+argument can be used to transfer data back to the server.
+- If a pointer to an object is passed to a callout (either a "raw"
+pointer, or a boost smart pointer (as in the example above), and the
+underlying object is altered through that pointer, the change will be
+reflected in the server even if no call is made to setArgument.
+
+In all cases, consult the documentation for the particular hook to see whether
+parameters can be modified.  As a general rule:
+
+- Do not alter arguments unless you mean the change to be reflected in
+the server.
+- If you alter an argument, call CalloutHandle::setArgument to update the
+value in the CalloutHandle object.
+
+ at subsubsection hooksdgSkipFlag The "Skip" Flag
+
+When a to callouts attached to a hook returns, the server will usually continue
+its processing.  However, a callout might have done something that means that
+the server should follow another path.  Possible actions a server could take
+include:
+
+- Skip the next stage of processing because the callout has already
+done it.  For example, a hook is located just before the DHCP server
+allocates an address to the client.  A callout may decide to allocate
+special addresses for certain clients, in which case it needs to tell
+the server not to allocate an address in this case.
+- Drop the packet and continue with the next request. A possible scenario
+is a DNS server where a callout inspects the source address of an incoming
+packet and compares it against a black list; if the address is on it,
+the callout notifies the server to drop the packet.
+
+To handle these common cases, the CalloutHandle has a "skip" flag.
+This is set by a callout when it wishes the server to skip normal
+processing.  It is set false by the hooks framework before callouts on a
+hook are called.  If the flag is set on return, the server will take the
+"skip" action relevant for the hook.
+
+The methods to get and set the "skip" flag are getSkip and setSkip. Their
+usage is intuitive:
+
+ at code
+    // Get the current setting of the skip flag.
+    bool skip = handle.getSkip();
+
+    // Do some processing...
+        :
+    if (lease_allocated) {
+        // Flag the server to skip the next step of the processing as we
+        // already have an address.
+        handle.setSkip(true);
+    }
+    return;
+    
+ at endcode
+
+Like arguments, the "skip" flag is passed to all callouts on a hook.  Callouts
+later in the list are able to examine (and modify) the settings of earlier ones.
+
+ at subsubsection hooksdgCalloutContext Per-Request Context
+
+Although many of the BIND 10 modules can be characterised as handling
+singles packet - e.g. the DHCPv4 server receives a DISCOVER packet,
+processes it and responds with an OFFER, this is not true in all cases.
+The principal exception is the recursive DNS resolver: this receives a
+packet from a client but that packet may itself generate multiple packets
+being sent to upstream servers. To avoid possible confusion the rest of
+this section uses the term "request" to indicate a request by a client
+for some information or action.
+
+As well as argument information, the CalloutHandle object can be used by
+callouts to attach information to a request being handled by the server.
+This information (known as "context") is not used by the server: its purpose
+is to allow callouts to pass information between one another on a
+per-request basis.
+
+Context only exists only for the duration of the request: when a request
+is completed, the context is destroyed.  A new request starts with no
+context information.  Context is particularly useful in servers that may
+be processing multiple requests simultaneously: callouts can effectively
+attach data to a request that follows the request around the system.
+
+Context information is held as name/value pairs in the same way
+as arguments, being accessed by the pair of methods setContext and
+getContext.  They have the same restrictions as the setArgument and
+getArgument methods - the type of data retrieved from context must
+<B>exactly</B> match the type of the data set.
+
+The example in the next section illustrates their use.
+
+ at subsection hooksdgExampleCallouts Example Callouts
+
+Continuing with the tutorial, the requirements need us to retrieve the
+hardware address of the incoming packet, classify it, and write it,
+together with the assigned IP address, to a log file.  Although we could
+do this in one callout, for this example we'll use two:
+
+- pkt_rcvd - a callout on this hook is invoked when a packet has been
+received and has been parsed.  It is passed a single argument, "query"
+which is an isc::dhcp::Pkt4 object (representing a DHCP v4 packet).
+We will do the classification here.
+
+- v4_lease_write_post - called when the lease (an assignment of an IPv4
+address to a client for a fixed period of time) has been written to the
+database. It is passed two arguments, the query ("query")
+and the response (called "reply").  This is the point at which the
+example code will write the hardware and IP addresses to the log file.
+
+The standard for naming callouts is to give them the same name as
+the hook.  If this is done, the callouts will be automatically found
+by the Hooks system (this is discussed further in section @ref
+hooksdgCalloutRegistration).  For our example, we will assume this is the
+case, so the code for the first callout (used to classify the client's
+hardware address) is:
+
+ at code
+// pkt_rcvd.cc
+
+#include <hooks/hooks.h>
+#include <dhcp/pkt4.h>
+#include "library_common.h"
+
+#include <string>
+
+using namespace isc::dhcp;
+using namespace std;
+
+extern "C" {
+
+// This callout is called at the "pkt_rcvd" hook.
+int pkt_rcvd(CalloutHandle& handle) {
+
+    // A pointer to the packet is passed to the callout via a "boost" smart
+    // pointer. The include file "pkt4.h" typedefs a pointer to the Pkt4
+    // object as Pkt4Ptr.  Retrieve a pointer to the object.
+    Pkt4Ptr query_ptr;
+    handle.getArgument("query", query_ptr);
+
+    // Point to the hardware address.
+    HwAddrPtr hwaddr_ptr = query_ptr->getHWAddr();
+
+    // The hardware address is held in a public member variable. We'll classify
+    // it as interesting if the sum of all the bytes in it is divisible by 4.
+    //  (This is a contrived example after all!)
+    long sum = 0;
+    for (int i = 0; i < hwaddr_ptr->hwaddr_.size(); ++i) {
+        sum += hwaddr_ptr->hwadr_[i];
+    }
+
+    // Classify it.
+    if (sum % 4 == 0) {
+        // Store the text form of the hardware address in the context to pass
+        // to the next callout.
+        handle.setContext("hwaddr", hwaddr_ptr->hwaddr_.toText());
+    }
+
+    return (0);
+};
+ at endcode
+
+The pct_rcvd callout placed the hardware address of an interesting client in
+the "hwaddr" context for the packet.  Turning now to the callout that will
+write this information to the log file:
+
+ at code
+// v4_lease_write.cc
+
+#include <hooks/hooks.h>
+#include <dhcp/pkt4.h>
+#include "library_common.h"
+
+#include <string>
+
+using namespace isc::dhcp;
+using namespace std;
+
+extern "C" {
+
+// This callout is called at the "v4_lease_write_post" hook.
+int v4_lease_write_post(CalloutHandle& handle) {
+
+    // Obtain the hardware address of the "interesting" client.  We have to
+    // use a try...catch block here because if the client was not interesting,
+    // no information would be set and getArgument would thrown an exception.
+    string hwaddr;
+    try (handle.getArgument("hwaddr", hwaddr) {
+
+        // getArgument didn't throw so the client is interesting.  Get a pointer
+        // to the reply.  Note that the argument list for this hook also
+        // contains a pointer to the query: we don't need to access that in this
+        // example.
+        Pkt4Ptr reply;
+        handle.getArgument("reply", reply);
+
+        // Get the string form of the IP address.
+        string ipaddr = reply->getYiaddr().toText();
+
+        // Write the information to the log file.
+        interesting << hwaddr << " " << ipaddr << "\n";
+
+        // ... and to guard against a crash, we'll flush the output stream.
+        flush(interesting);
+
+    } catch (const NoSuchCalloutContext&) {
+
+        // No such element in the per-request context with the name
+        // "hwaddr".  We will do nothing, so just dismiss the exception.
+
+    }
+
+    return (0);
+}
+
+};
+ at endcode
+
+ at subsection hooksdgBuild Building the Library
+
+Building the code requires building a shareable library.  This requires
+the the code be compiled as positition-independent code (using the
+compiler's "-fpic" switch) and linked as a shared library (with the
+linker's "-shared" switch).  The build command also needs to point to
+the BIND 10 include directory and link in the appropriate libraries.
+
+Assuming that BIND 10 has been installed in the default location, the
+command line needed to create the library using the Gnu C++ compiler on a
+Linux system is:
+
+ at code
+g++ -I /usr/include/bind10 -L /usr/lib/bind10 -fpic -shared -o example.so \
+    load_unload.cc pkt_rcvd.cc v4_lease_write.cc version.cc \
+    -lb10-dhcp++ -lb10-util -lb10-exceptions
+ at endcode
+
+Notes:
+- The compilation command and switches required may vary depending on
+your operating system and compiler - consult the relevant documentation
+for details.
+- The values for the "-I" and "-L" switches depend on where you have
+installed BIND 10.
+- The list of libraries that need to be included in the command line
+depends on the functionality used by the hook code and the module to
+which they are attached (e.g. hook code for DNS will need to link against
+the libb10-dns++ library).  Depending on operating system, you may also need
+to explicitly list libraries on which the BIND 10 libraries depend.
+
+ at subsection hooksdgConfiguration Configuring the Hook Library
+
+The final step is to make the library known to BIND 10.  All BIND 10 modules to
+which hooks can be added contain the "hook_library" element, and user
+libraries are added to this. (The BIND 10 hooks system can handle multiple libraries - this is discussed below.).
+
+To add the example library (assumed to be in /usr/local/lib) to the DHCPv4
+module, the following bindctl commands must be executed:
+
+ at code
+> config add Dhcp4/hook_libraries
+> config set Dhcp4/hook_libraries[0] "/usr/local/lib/example.so"
+> config commit
+ at endcode
+
+The DHCPv4 server will load the library and execute the callouts each time a
+request is received.
+
+ at section hooksdgAdvancedTopics Advanced Topics
+
+ at subsection hooksdgContextCreateDestroy Context Creation and Destruction
+
+As well as the hooks defined by the server, the hooks framework defines
+two hooks of its own, "context_create" and "context_destroy".  The first
+is called when a request is created in the server, before any of the
+server-specific hooks gets called.  It's purpose it to allow a library
+to initialize per-request context. The second is called after all
+server-defined hooks have been processed, and is to allow a library to
+tidy up.
+
+As an example, the v4_lease_write example above required that the code
+check for an exception being thrown when accessing the "hwaddr" context
+item in case it was not set.  An alternative strategy would have been to
+provide a callout for the "context_create" hook and set the context item
+"hwaddr" to an empty string. Instead of needing to handle an exception,
+v4_lease_write would be guaranteed to get something when looking for
+the hwaddr item and so could write or not write the output depending on
+the value.
+
+In most cases, "context_destroy" is not needed as the Hooks system
+automatically deletes context. An example where it could be required
+is where memory has been allocated by a callout during the processing
+of a request and a raw pointer to it stored in the context object. On
+destruction of the context, that memory will not be automatically
+released. Freeing in the memory in the "context_destroy callout will solve
+that problem.
+
+Actually, when the context is destroyed, the destructor
+associated with any objects stored in it are run. Rather than point to
+allocated memory with a raw pointer, a better idea would be to point to
+it with a boost "smart" pointer and store that pointer in the context.
+When the context is destroyed, the smart pointer's destructor is run,
+which will automatically delete the pointed-to object.
+
+These approaches are illustrated in the following examples.
+Here it is assumed that the hooks library is performing some form of
+security checking on the packet and needs to maintain information in
+a user-specified "SecurityInformation" object. (The details of this
+fictitious object are of no concern here.) The object is created in
+the context_create callout and used in both the pkt4_rcvd and the
+v4_lease_write_post callouts.
+
+ at code
+// Storing information in a "raw" pointer.  Assume that the
+
+#include <hooks/hooks.h>
+   :
+
+extern "C" {
+
+// context_create callout - called when the request is created.
+int context_create(CalloutHandle& handle) {
+    // Create the security information and store it in the context
+    // for this packet.
+    SecurityInformation* si = new SecurityInformation();
+    handle.setContext("security_information", si);
+}
+
+// Callouts that use the context
+int pktv_rcvd(CalloutHandle& handle) {
+    // Retrieve the pointer to the SecurityInformation object
+    SecurityInformation si;
+    handle.getContext("security_information", si);
+        :
+        :
+    // Set the security information
+    si->setSomething(...);
+
+    // The pointed-to information has been updated but the pointer has not been
+    // altered, so there is no need to call setContext() again.
+}
+
+int v4_lease_write_post(CalloutHandle& handle) {
+    // Retrieve the pointer to the SecurityInformation object
+    SecurityInformation si;
+    handle.getContext("security_information", si);
+        :
+        :
+    // Retrieve security information
+    bool active = si->getSomething(...);
+        :
+}
+
+// Context destruction.  We need to delete the pointed-to SecurityInformation
+// object because we will lose the pointer to it when the CalloutHandle is
+// destroyed.
+int context_destroy(CalloutHandle& handle) {
+    // Retrieve the pointer to the SecurityInformation object
+    SecurityInformation si;
+    handle.getContext("security_information", si);
+
+    // Delete the pointed-to memory.
+    delete si;
+}
+ at endcode
+
+The requirement for the context_destroy callout can be eliminated if
+a Boost shared ptr is used to point to the allocated memory:
+
+ at code
+// Storing information in a "raw" pointer.  Assume that the
+
+#include <hooks/hooks.h>
+#include <boost/shared_ptr.hpp>
+   :
+
+extern "C" {
+
+// context_create callout - called when the request is created.
+
+int context_create(CalloutHandle& handle) {
+    // Create the security information and store it in the context for this
+    // packet.
+    boost::shared_ptr<SecurityInformation> si(new SecurityInformation());
+    handle.setContext("security_information", si);
+}
+
+// Other than the data type, a shared pointer has similar semantics to a "raw"
+// pointer.  Only the code from pkt_rcvd is shown here.
+
+int pktv_rcvd(CalloutHandle& handle) {
+    // Retrieve the pointer to the SecurityInformation object
+    boost::shared_ptr<SecurityInformation> si;
+    handle.setContext("security_information", si);
+        :
+        :
+    // Modify the security information
+    si->setSomething(...);
+
+    // The pointed-to information has been updated but the pointer has not
+    // altered, so theree is no need to reset the context.
+}
+
+// No context_destroy callout is needed to delete the allocated
+// SecurityInformation object.  When the CalloutHandle is destroyed, the shared
+// pointer object will be destroyed.  If that is the last shared pointer to the
+// allocated memory, then it too will be deleted.
+ at endcode
+
+(Note that a Boost shared pointer - rather than any other Boost smart pointer -
+should be used, as the pointer objects are copied within the hooks framework and
+only shared pointers have the correct behavior for the copy operation.)
+
+
+ at subsection hooksdgCalloutRegistration Registering Callouts
+
+As briefly mentioned in @ref hooksdgExampleCallouts, the standard is for
+callouts in the user library to have the same name as the name of the
+hook to which they are being attached.  This convention was followed
+in the tutorial, e.g.  the callout that needed to be attached to the
+"pkt_rcvd" hook was named pkt_rcvd.
+
+The reason for this convention is that when the library is loaded, the
+hook framework automatically searches the library for functions with
+the same names as the server hooks.  When it finds one, it attaches it
+to the appropriate hook point.  This simplifies the loading process and
+bookkeeping required to create a library of callouts.
+
+However, the hooks system is flexible in this area: callouts can have
+non-standard names, and multiple callouts can be registered on a hook.
+
+ at subsubsection hooksdgLibraryHandle The LibraryHandle Object
+
+The way into the part of the hooks framework that allows callout
+registration is through the LibraryHandle object.  This was briefly
+introduced in the discussion of the framework functions, in that
+an object of this type is pass to the "load" function.  A LibraryHandle
+can also be obtained from within a callout by calling the CalloutHandle's
+getLibraryHandle() method.
+
+The LibraryHandle provides three methods to manipulate callouts:
+
+- registerCallout - register a callout on a hook.
+- deregisterCallout - deregister a callout from a hook.
+- deregisterAllCallouts - deregister all callouts on a hook.
+
+The following sections cover some of the ways in which these can be used.
+
+ at subsubsection hooksdgNonstandardCalloutNames Non-Standard Callout Names
+
+The example in the tutorial used standard names for the callouts.  As noted
+above, it is possible to use non-standard names.  Suppose, instead of the
+callout names "pkt_rcvd" and "v4_lease_write", we had named our callouts
+"classify" and "write_data".  The hooks framework would not have registered
+these callouts, so we would have needed to do it ourself.  The place to
+do this is the "load" framework function, and its code would have had to
+been modified to:
+
+ at code
+int load(LibraryHandle& libhandle) {
+    // Register the callouts on the hooks. We assume that a header file
+    // declares the "classify" and "write_data" functions.
+    libhandle.registerCallout("pkt_rcvd", classify);
+    libhandle.registerCallout("v4_lease_write", write_data);
+
+    // Open the log file
+    interesting.open("/data/clients/interesting.log",
+                     std::fstream::out | std::fstream::app);
+    return (interesting ? 0 : 1);
+}
+ at endcode
+
+It is possible for a library to contain callouts with both standard and
+non-standard names: ones with standard names will be registered automatically,
+ones with non-standard names need to be registered manually.
+
+ at subsubsection hooksdgMultipleCallouts Multiple Callouts on a Hook
+
+The BIND 10 hooks framework allows multiple callouts to be attached to 
+a hook point.  Although it is likely to be rare for user code to need to
+do this, there may be instances where it make sense.
+
+To register multiple callouts on a hook, just call
+LibraryHandle::registerCallout multiple times on the same hook, e.g.
+
+ at code
+    libhandle.registerCallout("pkt_rcvd", classify);
+    libhandle.registerCallout("pkt_rcvd", write_data);
+ at endcode
+
+The hooks framework will call the callouts in the order they are
+registered.  The same CalloutHandle is passed between them, so any
+change made to the CalloutHandle's arguments, "skip" flag, or per-request
+context by the first is visible to the second.
+
+ at subsubsection hooksdgDynamicRegistration Dynamic Registration and Reregistration of Callouts
+
+The previous sections have dealt with callouts being registered during
+the call to "load".  The hooks framework is more flexible than that
+in that callouts can be registered and deregistered within a callout.
+In fact, a callout is able to register or deregister itself, and a callout
+is able to be registered on a hook multiple times.
+
+Using our contrived example again, the DHCPv4 server processes one request
+to completion before it starts processing the next.  With this knowledge,
+we could alter the logic of the code so that the callout attached to the
+"pkt_rcvd" hook registers the callout doing the logging when it detects
+an interesting packet, and the callout doing the logging deregisters
+itself in its execution.  The relevant modifications to the code in
+the tutorial are shown below:
+
+ at code
+// pkt_rcvd.cc
+//      :
+
+int pkt_rcvd(CalloutHandle& handle) {
+
+            :
+            :
+
+    // Classify it.
+    if (sum % 4 == 0) {
+        // Store the text form of the hardware address in the context to pass
+        // to the next callout.
+        handle.setContext("hwaddr", hwaddr_ptr->hwaddr_.toText());
+
+        // Register the callback to log the data.
+        handle.getLibraryHandle().registerCallout("v4_lease_write", write_data);
+    }
+
+    return (0);
+};
+ at endcode
+
+ at code
+// v4_lease_write.cc
+        :
+
+int write_data(CalloutHandle& handle) {
+
+    // Obtain the hardware address of the "interesting" client. As the
+    // callback is only registered when interesting data is present, we
+    // know that the context contains the hardware address so an exception
+    // will not be thrown when we call getArgument().
+    string hwaddr;
+    handle.getArgument("hwaddr", hwaddr);
+
+    // The pointer to the reply.
+    ConstPkt4Ptr reply;
+    handle.getArgument("reply", reply);
+
+    // Get the string form of the IP address.
+    string ipaddr = reply->getYiaddr().toText():
+
+    // Write the information to the log file and flush.
+    interesting << hwaddr << " " << ipaddr << "\n";
+    flush(interesting);
+
+    // We've logged the data, so deregister ourself.  This callout will not
+    // be called again until it is registered by pkt_rcvd.
+
+    handle.getLibraryHandle().deregisterCallout("v4_lease_write", write_data);
+
+    return (0);
+}
+ at endcode
+
+Note that the above example used a non-standard name for the callout
+that wrote the data.  Had the name been a standard one, it would have been
+registered when the library was loaded and called for the first request,
+regardless of whether that was defined as "interesting".  (Although as
+callouts with standard names are always registered before "load" gets called,
+we could have got round that problem by deregistering that particular
+callout in the "load" function.)
+
+
+ at note Deregistration of a callout on the hook that is currently
+being called only takes effect when the server next calls the hook.
+To illustrate this, suppose the callouts attached to a hook are A, B and C
+(in that order), and during execution, A deregisters B and C and adds D.
+When callout A returns, B and C will still run.  The next time the server
+calls the hook's callouts, A and D will run (in that order).
+
+ at subsection hooksdgMultipleLibraries Multiple User Libraries
+
+As alluded to in the section @ref hooksdgConfiguration, BIND 10 can load
+multiple libraries.  The libraries are loaded in the order specified in
+the configuration, and the callouts attached to the hooks in the order
+presented by the libraries.
+
+The following picture illustrates this, and also illustrates the scope of
+data passed around the system.
+
+ at image html DataScopeArgument.png "Scope of Arguments"
+
+In this illustration, a server has three hook points, alpha, beta
+and gamma.  Two libraries are configured, library 1 and library 2.
+Library 1 registers the callout "authorize" for hook alpha, "check" for
+hook beta and "add_option" for hook gamma.  Library 2 registers "logpkt",
+"validate" and "putopt"
+
+The horizontal red lines represent arguments to callouts.  When the server
+calls hook alpha, it creates an argument list and calls the
+first callout for the hook, "authorize".  When that callout returns, the
+same (but possibly modified) argument list is passed to the next callout
+in the chain, "logpkt".  Another, separate argument list is created for
+hook beta and passed to the callouts "check" and "validate" in
+that order.  A similar sequence occurs for hook gamma.
+
+The next picture shows the scope of the context associated with a
+request.
+
+ at image html DataScopeContext.png "Illustration of per-library context"
+
+The vertical blue lines represent callout context. Context is
+per-packet but also per-library.  When the server calls "authorize",
+the CalloutHandle's getContext and setContext methods access a context
+created purely for library 1. The next callout on the hook will access
+context created for library 2. These contexts are passed to the callouts
+associated with the next hook.  So when "check" is called, it gets the
+context data that was set by "authorize", when "validate" is called,
+it gets the context data set by "logpkt".
+
+It is stressed that the context for callouts associated with different
+libraries is entirely separate.  For example, suppose "authorize" sets
+the CalloutHandle's context item "foo" to 2 and "logpkt" sets an item of
+the same name to the string "bar".  When "check" accesses the context
+item "foo", it gets a value of 2; when "validate" accesses an item of
+the same name, it gets the value "bar".
+
+It is also stressed that all this context exists only for the life of the
+request being processed.  When that request is complete, all the
+context associated with that request - for all libraries - is destroyed,
+and new context created for the next request.
+
+This structure means that library authors can use per-request context
+without worrying about the presence of other libraries.  Other libraries
+may be present, but will not affect the context values set by a library's
+callouts.
+
+ at subsection hooksdgInterLibraryData Passing Data Between Libraries
+
+In rare cases, it is possible that one library may want to pass
+data to another.  This can be done in a limited way by means of the
+CalloutHandle's setArgument and getArgument calls.  For example, in the
+above diagram, the callout "add_option" can pass a value to "putopt"
+by setting a name.value pair in the hook's argument list.  "putopt"
+would be able to read this, but would not be able to return information
+back to "add_option".
+
+All argument names used by BIND 10 will be a combination of letters
+(both upper- and lower-case), digits, hyphens and underscores: no
+other characters will be used.  As argument names are simple strings,
+it is suggested that if such a mechanism be used, the names of the data
+values passed between the libraries include a special character such as
+the dollar symbol or percent sign.  In this way there is no danger that
+a name will conflict with any existing or future BIND 10 argument names.
+
+
+ at subsection hooksdgRegisterMultipleLibraries Dynamic Callout Registration and Multiple Libraries
+
+On a particular hook, callouts are called in the order the libraries appear
+in the configuration and, within a library, in the order the callouts
+are registered.
+
+This order applies to dynamically-registered callouts as well.  As an
+example, consider the diagram above where for hook "beta", callout "check"
+is followed by callout "validate".  Suppose that when "authorize" is run,
+it registers a new callout ("double_check") on hook "beta".  That
+callout will be inserted at the end of the callouts registered by
+library 1 and before any registered by library 2.  It would therefore
+appear between "check" and "validate".  On the other hand, if it were
+"logpkt" that registered the new callout, "double_check" would appear
+after "validate".
+
+*/
diff --git a/src/lib/hooks/images/HooksUml.dia b/src/lib/hooks/images/HooksUml.dia
new file mode 100644
index 0000000..0972fca
Binary files /dev/null and b/src/lib/hooks/images/HooksUml.dia differ
diff --git a/src/lib/hooks/images/HooksUml.png b/src/lib/hooks/images/HooksUml.png
new file mode 100644
index 0000000..3859e6a
Binary files /dev/null and b/src/lib/hooks/images/HooksUml.png differ



More information about the bind10-changes mailing list