mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
[2982] Updates to address review comments
This commit is contained in:
@@ -36,22 +36,22 @@
|
|||||||
* Regardless of your field of expertise, you are encouraged to visit
|
* Regardless of your field of expertise, you are encouraged to visit
|
||||||
* <a href="http://bind10.isc.org/">BIND10 webpage (http://bind10.isc.org)</a>
|
* <a href="http://bind10.isc.org/">BIND10 webpage (http://bind10.isc.org)</a>
|
||||||
*
|
*
|
||||||
* @section hookDevelopersGuide
|
* @section hooksdgDevelopersGuide
|
||||||
* - @subpage hookIntroduction
|
* - @subpage hooksdgIntroduction
|
||||||
* - @subpage hookLanguages
|
* - @subpage hooksdgLanguages
|
||||||
* - @subpage hookTerminology
|
* - @subpage hooksdgTerminology
|
||||||
* - @subpage hookTutorial
|
* - @subpage hooksdgTutorial
|
||||||
* - @subpage hookFrameworkFunctions
|
* - @subpage hooksdgFrameworkFunctions
|
||||||
* - @subpage hookCallouts
|
* - @subpage hooksdgCallouts
|
||||||
* - @subpage hookExampleCallouts
|
* - @subpage hooksdgExampleCallouts
|
||||||
* - @subpage hookBuild
|
* - @subpage hooksdgBuild
|
||||||
* - @subpage hookConfiguration
|
* - @subpage hooksdgConfiguration
|
||||||
* - @subpage hookAdvancedTopics
|
* - @subpage hooksdgAdvancedTopics
|
||||||
* - @subpage hookContextCreateDestroy
|
* - @subpage hooksdgContextCreateDestroy
|
||||||
* - @subpage hookCalloutRegistration
|
* - @subpage hooksdgCalloutRegistration
|
||||||
* - @subpage hookMultipleLibraries
|
* - @subpage hooksdgMultipleLibraries
|
||||||
* - @subpage hookInterLibraryData
|
* - @subpage hooksdgInterLibraryData
|
||||||
* - @subpage hookRegisterMultipleLibraries
|
* - @subpage hooksdgRegisterMultipleLibraries
|
||||||
*
|
*
|
||||||
* @section dnsMaintenanceGuide DNS Maintenance Guide
|
* @section dnsMaintenanceGuide DNS Maintenance Guide
|
||||||
* - Authoritative DNS (todo)
|
* - Authoritative DNS (todo)
|
||||||
|
@@ -12,10 +12,14 @@
|
|||||||
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
// PERFORMANCE OF THIS SOFTWARE.
|
// PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
/**
|
// Note: the prefix "hooksdg" to all labels is an abbreviation for "Hooks
|
||||||
@page hookDevelopersGuide Hook Developer's Guide
|
// Developer's Guide" and is used to prevent a clash with symbols in any
|
||||||
|
// other Doxygen file.
|
||||||
|
|
||||||
@section hookIntroduction Introduction
|
/**
|
||||||
|
@page hooksdgDevelopersGuide Hook Developer's Guide
|
||||||
|
|
||||||
|
@section hooksdgIntroduction Introduction
|
||||||
|
|
||||||
Although the BIND 10 framework and its associated DNS and DHCP programs
|
Although the BIND 10 framework and its associated DNS and DHCP programs
|
||||||
provide comprehensive functionality, there will be times when it does
|
provide comprehensive functionality, there will be times when it does
|
||||||
@@ -31,7 +35,7 @@ understanding how it works will take a significant amount of time. In
|
|||||||
addition, despite the fact that its object-oriented design keeps the
|
addition, despite the fact that its object-oriented design keeps the
|
||||||
coupling between modules to a minimum, an inappropriate change to one
|
coupling between modules to a minimum, an inappropriate change to one
|
||||||
part of the program during the extension could cause another to
|
part of the program during the extension could cause another to
|
||||||
behave oddly or to stop working altogether, adding to development time.
|
behave oddly or to stop working altogether.
|
||||||
|
|
||||||
- The change may need to be re-applied or re-written with every new
|
- 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,
|
version of BIND 10. As new functionality is added or bugs are fixed,
|
||||||
@@ -39,59 +43,59 @@ the code or algorithms in the core software may change - and may change
|
|||||||
significantly.
|
significantly.
|
||||||
|
|
||||||
To overcome these problems, BIND 10 provides the "Hooks" interface -
|
To overcome these problems, BIND 10 provides the "Hooks" interface -
|
||||||
a defined interface for third-party or user-written code (for ease of
|
a defined interface for third-party or user-written code. (For ease of
|
||||||
reference in the rest of this document, such code will be referred to
|
reference in the rest of this document, all such code will be referred
|
||||||
as "user-written code"). At specific points in its processing ("hook
|
to as "user code".) At specific points in its processing
|
||||||
points") BIND 10 will make a call to this code. The call passes data
|
("hook points") BIND 10 will make a call to this code. The call passes
|
||||||
that the user can examine and, if required, modify. BIND 10 used the
|
data that the user code can examine and, if required, modify.
|
||||||
modified code in the remainder of its processing.
|
BIND 10 uses the modified data in the remainder of its processing.
|
||||||
|
|
||||||
In order to minimise the interaction between BIND 10 and the
|
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
|
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
|
a shared library (or libraries). These are made known to BIND 10
|
||||||
through its configuration mechanism, and BIND 10 loads the library at
|
through its configuration mechanism, and BIND 10 loads the library at
|
||||||
run time. Libraries can be unloaded and reloaded as needed while BIND
|
run time. Libraries can be unloaded and reloaded as needed while BIND
|
||||||
10 is running.
|
10 is running.
|
||||||
|
|
||||||
Use of a defined API and BIND 10 configuration mechanism means that as
|
Use of a defined API and the BIND 10 configuration mechanism means that
|
||||||
new versions of BIND 10 are released, there is no need to modify the
|
as new versions of BIND 10 are released, there is no need to modify
|
||||||
user-written code. Unless there is a major change in an interface
|
the user code. Unless there is a major change in an interface
|
||||||
(which will be clearly documented) all that will be required is a
|
(which will be clearly documented), all that will be required is a rebuild
|
||||||
rebuild of the libraries.
|
of the libraries.
|
||||||
|
|
||||||
@note Although the defined interface should not change, the internals
|
@note Although the defined interface should not change, the internals
|
||||||
of some of the classes and structures referenced by the user-written
|
of some of the classes and structures referenced by the user code may
|
||||||
code may alter. These changes will need to be reflected in the compiled
|
change between versions of BIND 10. These changes have to be reflected
|
||||||
version of the software, hence the need for a rebuild.
|
in the compiled version of the software, hence the need for a rebuild.
|
||||||
|
|
||||||
@subsection hookLanguages Languages
|
@subsection hooksdgLanguages Languages
|
||||||
|
|
||||||
The core of BIND 10 is written in C++. While it is the intention to
|
The core of BIND 10 is written in C++. While it is the intention to
|
||||||
provide interfaces into user code written into other languages, the
|
provide interfaces into user code written in other languages, the initial
|
||||||
initial versions of the Hooks system requires that user code be written
|
versions of the Hooks system requires that user code be written in C++.
|
||||||
in C++. All examples in this guide are in that language.
|
All examples in this guide are in that language.
|
||||||
|
|
||||||
@subsection hookTerminology Terminology
|
@subsection hooksdgTerminology Terminology
|
||||||
|
|
||||||
In the remainder of this guide, the following terminology is used:
|
In the remainder of this guide, the following terminology is used:
|
||||||
|
|
||||||
- Hook/Hook Point - used interchageably, this is a point in the code at
|
- Hook/Hook Point - used interchageably, this is a point in the code at
|
||||||
which a call to user-written functions is made. Each hook has a name and
|
which a call to user functions is made. Each hook has a name and
|
||||||
each hook can have any number (including 0) of user-written functions
|
each hook can have any number (including 0) of user functions
|
||||||
attached to it.
|
attached to it.
|
||||||
|
|
||||||
- Callout - a user-written function called by the server at a hook
|
- Callout - a user function called by the server at a hook
|
||||||
point. This is so-named because the server "calls out" to the library
|
point. This is so-named because the server "calls out" to the library
|
||||||
to execute a user-written function.
|
to execute a user function.
|
||||||
|
|
||||||
- Framework function - the functions that a user-written library needs to
|
- Framework function - the functions that a user library needs to
|
||||||
supply in order for the hooks framework for load and unload the library.
|
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
|
- User code/user library - non-BIND 10 code that is compiled into a
|
||||||
shared library and loaded by BIND 10 into its address space.
|
shared library and loaded by BIND 10 into its address space.
|
||||||
|
|
||||||
|
|
||||||
@section hookTutorial Tutorial
|
@section hooksdgTutorial Tutorial
|
||||||
|
|
||||||
To illustrate how to write code that integrates with BIND 10, we will
|
To illustrate how to write code that integrates with BIND 10, we will
|
||||||
use the following (rather contrived) example:
|
use the following (rather contrived) example:
|
||||||
@@ -103,14 +107,14 @@ 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 hardware address and allocated IP address for the clients of interest.
|
||||||
|
|
||||||
The following sections describe how to implement these requirements.
|
The following sections describe how to implement these requirements.
|
||||||
The code presented here is not efficient and there are better ways
|
The code presented here is not efficient and there are better ways of
|
||||||
of doing the task. The aim is to illustrate the main features of
|
doing the task. The aim however, is to illustrate the main features of
|
||||||
user-written hook code rather than provide an optimal solution.
|
user hook code not to provide an optimal solution.
|
||||||
|
|
||||||
|
|
||||||
@subsection hookFrameworkFunctions Framework Functions
|
@subsection hooksdgFrameworkFunctions Framework Functions
|
||||||
|
|
||||||
Loading an initializing a library holding user-written code makes use
|
Loading and initializing a library holding user code makes use
|
||||||
of three (user-supplied) functions:
|
of three (user-supplied) functions:
|
||||||
|
|
||||||
- version - defines the version of BIND 10 code with which the user-library
|
- version - defines the version of BIND 10 code with which the user-library
|
||||||
@@ -118,10 +122,10 @@ is built
|
|||||||
- load - called when the library is loaded by the server.
|
- load - called when the library is loaded by the server.
|
||||||
- unload - called when the library is unloaded by the server.
|
- unload - called when the library is unloaded by the server.
|
||||||
|
|
||||||
Of these, only "version" is mandatory, although our in out example, all three
|
Of these, only "version" is mandatory, although our in our example, all three
|
||||||
are used.
|
are used.
|
||||||
|
|
||||||
@subsubsection hookVersionFunction The "version" Function
|
@subsubsection hooksdgVersionFunction The "version" Function
|
||||||
|
|
||||||
"version" is used by the hooks framework to check that the libraries
|
"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.
|
it is loading are compatible with the version of BIND 10 being run.
|
||||||
@@ -129,14 +133,14 @@ Although the hooks system allows BIND 10 and user code to interface
|
|||||||
through a defined API, the relationship is somewhat tight in that the
|
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
|
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
|
change - as they can between BIND 10 releases - and BIND 10 is run with
|
||||||
a version of user-written code built against an earlier version of BIND
|
a version of user code built against an earlier version of BIND
|
||||||
10, a program crash could result.
|
10, a program crash could result.
|
||||||
|
|
||||||
To guard against this, the "version" function must be provided in
|
To guard against this, the "version" function must be provided in every
|
||||||
every library. It returns a constant defined in the version of header
|
library. It returns a constant defined in header files of the version
|
||||||
files against which it was built. The hooks framework checks this for
|
of BIND 10 against which it was built. The hooks framework checks this
|
||||||
compatibility with the running version of BIND 10 before proceeding with
|
for compatibility with the running version of BIND 10 before loading
|
||||||
the library load.
|
the library.
|
||||||
|
|
||||||
In this tutorial, we'll put "version" in its own file, version.cc. The
|
In this tutorial, we'll put "version" in its own file, version.cc. The
|
||||||
contents are:
|
contents are:
|
||||||
@@ -155,10 +159,11 @@ int version() {
|
|||||||
};
|
};
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The file "hooks/hooks.h" is specified relative to the BIND 10 libraries source
|
The file "hooks/hooks.h" is specified relative to the BIND 10 libraries
|
||||||
directory - this is covered later in the section @ref hookBuild. It defines the
|
source directory - this is covered later in the section @ref hooksdgBuild.
|
||||||
symbol BIND10_HOOKS_VERSION, which has a value that changes on every release
|
It defines the symbol BIND10_HOOKS_VERSION, which has a value that changes
|
||||||
of BIND 10: this is the value that needs to be returned to the hooks framework.
|
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
|
A final point to note is that the definition of "version" is enclosed
|
||||||
within 'extern "C"' braces. All functions accessed by the hooks
|
within 'extern "C"' braces. All functions accessed by the hooks
|
||||||
@@ -166,31 +171,36 @@ framework use C linkage, mainly to avoid the name mangling that
|
|||||||
accompanies use of the C++ compiler, but also to avoid issues related
|
accompanies use of the C++ compiler, but also to avoid issues related
|
||||||
to namespaces.
|
to namespaces.
|
||||||
|
|
||||||
@subsubsection hookLoadUnloadFunctions The "load" and "unload" Functions
|
@subsubsection hooksdgLoadUnloadFunctions The "load" and "unload" Functions
|
||||||
|
|
||||||
As the names suggest, "load" is called when a library is loaded and
|
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"
|
"unload" called when it is unloaded. (It is always guaranteed that
|
||||||
is called: "unload" may not be called in some circumstances, e.g. if the
|
"load" is called: "unload" may not be called in some circumstances,
|
||||||
system shuts down abnormally.) These functions are the places where any
|
e.g. if the system shuts down abnormally.) These functions are the
|
||||||
library-wide resources are allocated and deallocated. "load" is also
|
places where any library-wide resources are allocated and deallocated.
|
||||||
the place where any callouts with non-standard names can be registered:
|
"load" is also the place where any callouts with non-standard names
|
||||||
this is covered further in the section @ref hookCalloutRegistration.
|
(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,
|
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
|
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
|
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:
|
it in "unload".
|
||||||
|
|
||||||
|
We create two files, one for the file handle declaration:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
// library_common.h
|
// library_common.h
|
||||||
|
|
||||||
#ifndef LIBRARY_COMMON_H
|
#ifndef LIBRARY_COMMON_H
|
||||||
#define LIBRARY_COMMON_H
|
#define LIBRARY_COMMON_H
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
// "Interesting clients" log file handle declaration.
|
// "Interesting clients" log file handle declaration.
|
||||||
extern std::fstream interesting;
|
extern std::fstream interesting;
|
||||||
#endif
|
|
||||||
|
#endif // LIBRARY_COMMON_H
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
... and one to hold the "load" and "unload" functions:
|
... and one to hold the "load" and "unload" functions:
|
||||||
@@ -227,37 +237,40 @@ Notes:
|
|||||||
outside of any function. This means it can be accessed by any function
|
outside of any function. This means it can be accessed by any function
|
||||||
within the user library. For convenience, the definition is in the
|
within the user library. For convenience, the definition is in the
|
||||||
load_unload.cc file.
|
load_unload.cc file.
|
||||||
- "load" is called with a LibraryHandle argument, used in the registration
|
- "load" is called with a LibraryHandle argument, this being used in
|
||||||
of functions. As no functions are being called in this example,
|
the registration of functions. As no functions are being registered
|
||||||
the argument specification omits the variable name (whilst retaining the type)
|
in this example, the argument specification omits the variable name
|
||||||
to avoid an "unused variable" compiler warning. (The LibraryHandle is
|
(whilst retaining the type) to avoid an "unused variable" compiler
|
||||||
discussed in the section @ref hookLibraryHandle.)
|
warning. (The LibraryHandle and its use is discussed in the section
|
||||||
|
@ref hooksdgLibraryHandle.)
|
||||||
- In the current version of the hooks framework, it is not possible to pass
|
- 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
|
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
|
file must therefore be hard-coded as an absolute path name or communicated
|
||||||
to the user-written code by some other means.
|
to the user code by some other means.
|
||||||
- "load" returns 0 on success and non-zero on error. The hooks framework
|
- "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.
|
will abandon the loading of the library if "load" returns an error status.
|
||||||
(In this example, "interesting" can be tested as a boolean value,
|
(In this example, "interesting" can be tested as a boolean value,
|
||||||
returning "true" if the file opened successfully.)
|
returning "true" if the file opened successfully.)
|
||||||
- "unload" closes the log file if it is open and is a no-op otherwise. As
|
- "unload" closes the log file if it is open and is a no-op otherwise. As
|
||||||
with "load", a zero value is returned on success and a non-zero value
|
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
|
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 an error in the current BIND 10 log but otherwise ignore it.
|
||||||
- As before, the function definitions are enclosed in 'extern "C"' braces.
|
- As before, the function definitions are enclosed in 'extern "C"' braces.
|
||||||
|
|
||||||
@subsection hookCallouts Callouts
|
@subsection hooksdgCallouts Callouts
|
||||||
|
|
||||||
Having sorted out the framework, we now come to the functions that
|
Having sorted out the framework, we now come to the functions that
|
||||||
actually do something. These functions are known as "callouts" because
|
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
|
the BIND 10 code "calls out" to them. Each BIND 10 server has a number of
|
||||||
of hooks to which callouts can be attached: the purpose of the hooks
|
hooks to which callouts can be attached: server-specific documentation
|
||||||
and the data passed to callouts is documented elsewhere.
|
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
|
Before we continue with the example, we'll discuss how arguments are
|
||||||
passed to callouts and how information can be moved between them.
|
passed to callouts and information is returned to the server. We will
|
||||||
|
also discuss how information can be moved between callouts.
|
||||||
|
|
||||||
@subsubsection hookCalloutSignature The Callout Signature
|
@subsubsection hooksdgCalloutSignature The Callout Signature
|
||||||
|
|
||||||
All callouts are declared with the signature:
|
All callouts are declared with the signature:
|
||||||
@code
|
@code
|
||||||
@@ -279,7 +292,7 @@ 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
|
Effectively the return status provides a quick way for a callout to log
|
||||||
error information to the BIND 10 logging system.
|
error information to the BIND 10 logging system.
|
||||||
|
|
||||||
@subsubsection hookArguments Callout Arguments
|
@subsubsection hooksdgArguments Callout Arguments
|
||||||
|
|
||||||
The CalloutHandle object provides two methods to get and set the
|
The CalloutHandle object provides two methods to get and set the
|
||||||
arguments passed to the callout. These methods are called (naturally
|
arguments passed to the callout. These methods are called (naturally
|
||||||
@@ -296,7 +309,7 @@ following code snippets.
|
|||||||
handle.setArgument("data_count", count);
|
handle.setArgument("data_count", count);
|
||||||
handle.setArgument("inpacket", pktptr);
|
handle.setArgument("inpacket", pktptr);
|
||||||
|
|
||||||
// Call the hook code...
|
// Call the callouts attached to the hook
|
||||||
...
|
...
|
||||||
|
|
||||||
// Retrieve the modified values
|
// Retrieve the modified values
|
||||||
@@ -342,15 +355,13 @@ 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
|
"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
|
be retrieved into an "int".) The documentation of each hook point will
|
||||||
detail the data type of each argument.
|
detail the data type of each argument.
|
||||||
|
|
||||||
- Although all arguments can be modified, some altered values may not
|
- Although all arguments can be modified, some altered values may not
|
||||||
be read by the server. (These would be ones that the server considers
|
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
|
"read-only".) Consult the documentation of each hook to see whether an
|
||||||
argument can be used to transfer data back to the server.
|
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"
|
- 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
|
pointer, or a boost smart pointer (as in the example above), and the
|
||||||
underlying object altered through that pointer, the change will be
|
underlying object is altered through that pointer, the change will be
|
||||||
reflected in the server even if no call is made to setArgument.
|
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
|
In all cases, consult the documentation for the particular hook to see whether
|
||||||
@@ -361,10 +372,54 @@ the server.
|
|||||||
- If you alter an argument, call CalloutHandle::setArgument to update the
|
- If you alter an argument, call CalloutHandle::setArgument to update the
|
||||||
value in the CalloutHandle object.
|
value in the CalloutHandle object.
|
||||||
|
|
||||||
@subsubsection hookCalloutContext Per-Request Context
|
@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:
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
@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.
|
||||||
|
|
||||||
|
@subsubsection hooksdgCalloutContext Per-Request Context
|
||||||
|
|
||||||
Although many of the BIND 10 modules can be characterised as handling
|
Although many of the BIND 10 modules can be characterised as handling
|
||||||
a single packet - e.g. the DHCPv4 server receives a DISCOVER packet,
|
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.
|
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
|
The principal exception is the recursive DNS resolver: this receives a
|
||||||
packet from a client but that packet may itself generate multiple packets
|
packet from a client but that packet may itself generate multiple packets
|
||||||
@@ -381,9 +436,8 @@ per-request basis.
|
|||||||
Context only exists only for the duration of the request: when a request
|
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
|
is completed, the context is destroyed. A new request starts with no
|
||||||
context information. Context is particularly useful in servers that may
|
context information. Context is particularly useful in servers that may
|
||||||
be processing multiple requests simultaneously: callouts are effectively
|
be processing multiple requests simultaneously: callouts can effectively
|
||||||
attaching data to a request and that data follows the request around the
|
attach data to a request that follows the request around the system.
|
||||||
system.
|
|
||||||
|
|
||||||
Context information is held as name/value pairs in the same way
|
Context information is held as name/value pairs in the same way
|
||||||
as arguments, being accessed by the pair of methods setContext and
|
as arguments, being accessed by the pair of methods setContext and
|
||||||
@@ -391,11 +445,9 @@ getContext. They have the same restrictions as the setArgument and
|
|||||||
getArgument methods - the type of data retrieved from context must
|
getArgument methods - the type of data retrieved from context must
|
||||||
<B>exactly</B> match the type of the data set.
|
<B>exactly</B> match the type of the data set.
|
||||||
|
|
||||||
As the example in the tutorial uses per-request context, no separate
|
The example in the next section illustrates their use.
|
||||||
example is given here.
|
|
||||||
|
|
||||||
|
@subsection hooksdgExampleCallouts Example Callouts
|
||||||
@subsection hookExampleCallouts Example Callouts
|
|
||||||
|
|
||||||
Continuing with the tutorial, the requirements need us to retrieve the
|
Continuing with the tutorial, the requirements need us to retrieve the
|
||||||
hardware address of the incoming packet, classify it, and write it,
|
hardware address of the incoming packet, classify it, and write it,
|
||||||
@@ -409,14 +461,14 @@ We will do the classification here.
|
|||||||
|
|
||||||
- v4_lease_write_post - called when the lease (an assignment of an IPv4
|
- 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
|
address to a client for a fixed period of time) has been written to the
|
||||||
database. It is passed two (constant) arguments, the query ("query")
|
database. It is passed two arguments, the query ("query")
|
||||||
and the response (called "reply"). This is the point at which the
|
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.
|
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 standard for naming callouts is to give them the same name as
|
||||||
the hook. If this is done, the callouts will be automatically found
|
the hook. If this is done, the callouts will be automatically found
|
||||||
by the Hooks system (this is discussed further in section @ref
|
by the Hooks system (this is discussed further in section @ref
|
||||||
hookCalloutRegistration). For our example, we will assume this is the
|
hooksdgCalloutRegistration). For our example, we will assume this is the
|
||||||
case, so the code for the first callout (used to classify the client's
|
case, so the code for the first callout (used to classify the client's
|
||||||
hardware address) is:
|
hardware address) is:
|
||||||
|
|
||||||
@@ -435,7 +487,6 @@ using namespace std;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
// This callout is called at the "pkt_rcvd" hook.
|
// This callout is called at the "pkt_rcvd" hook.
|
||||||
|
|
||||||
int pkt_rcvd(CalloutHandle& handle) {
|
int pkt_rcvd(CalloutHandle& handle) {
|
||||||
|
|
||||||
// A pointer to the packet is passed to the callout via a "boost" smart
|
// A pointer to the packet is passed to the callout via a "boost" smart
|
||||||
@@ -485,7 +536,6 @@ using namespace std;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
// This callout is called at the "v4_lease_write_post" hook.
|
// This callout is called at the "v4_lease_write_post" hook.
|
||||||
|
|
||||||
int v4_lease_write_post(CalloutHandle& handle) {
|
int v4_lease_write_post(CalloutHandle& handle) {
|
||||||
|
|
||||||
// Obtain the hardware address of the "interesting" client. We have to
|
// Obtain the hardware address of the "interesting" client. We have to
|
||||||
@@ -495,10 +545,10 @@ int v4_lease_write_post(CalloutHandle& handle) {
|
|||||||
try (handle.getArgument("hwaddr", hwaddr) {
|
try (handle.getArgument("hwaddr", hwaddr) {
|
||||||
|
|
||||||
// getArgument didn't throw so the client is interesting. Get a pointer
|
// getArgument didn't throw so the client is interesting. Get a pointer
|
||||||
// to the reply. This is read-only so is passed through a smart pointer
|
// to the reply. Note that the argument list for this hook also
|
||||||
// const Pkt4 object. Note that the argument list also contains a
|
// contains a pointer to the query: we don't need to access that in this
|
||||||
// pointer to the query: we don't need to access that in this example.
|
// example.
|
||||||
ConstPkt4Ptr reply;
|
Pkt4Ptr reply;
|
||||||
handle.getArgument("reply", reply);
|
handle.getArgument("reply", reply);
|
||||||
|
|
||||||
// Get the string form of the IP address.
|
// Get the string form of the IP address.
|
||||||
@@ -523,13 +573,13 @@ int v4_lease_write_post(CalloutHandle& handle) {
|
|||||||
};
|
};
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@subsection hookBuild Building the Library
|
@subsection hooksdgBuild Building the Library
|
||||||
|
|
||||||
Building the code requires building a shareable library. This requires
|
Building the code requires building a shareable library. This requires
|
||||||
the the code be compiled as positition-independent code (using the
|
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
|
compiler's "-fpic" switch) and linked as a shared library (with the
|
||||||
-shared switch). The build command also needs to point to the BIND 10 include
|
linker's "-shared" switch). The build command also needs to point to
|
||||||
directory and link in the appropriate libraries.
|
the BIND 10 include directory and link in the appropriate libraries.
|
||||||
|
|
||||||
Assuming that BIND 10 has been installed in the default location, the
|
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
|
command line needed to create the library using the Gnu C++ compiler on a
|
||||||
@@ -542,20 +592,18 @@ g++ -I /usr/include/bind10 -L /usr/lib/bind10 -fpic -shared -o example.so \
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- the compilation command and switches required may vary depending on
|
- The compilation command and switches required may vary depending on
|
||||||
your operating system and compiler - consult the relevant documentation
|
your operating system and compiler - consult the relevant documentation
|
||||||
for details.
|
for details.
|
||||||
- the values for the -I and -L switches depend on where you have installed
|
- The values for the "-I" and "-L" switches depend on where you have
|
||||||
BIND 10.
|
installed BIND 10.
|
||||||
- the list of libraries that need to be included in the command line
|
- 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
|
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
|
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
|
the libb10-dns++ library). Depending on operating system, you may also need
|
||||||
to explicitly list libraries on which the BIND 10 libraries depend, e.g.
|
to explicitly list libraries on which the BIND 10 libraries depend.
|
||||||
in the command line above, libb10-exceptions depends on log4cplus, so it
|
|
||||||
is possible that "-llog4cplus" may need to be appended to the command line.
|
|
||||||
|
|
||||||
@subsection hookConfiguration Configuring the Hook Library
|
@subsection hooksdgConfiguration Configuring the Hook Library
|
||||||
|
|
||||||
The final step is to make the library known to BIND 10. All BIND 10 modules to
|
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
|
which hooks can be added contain the "hook_library" element, and user
|
||||||
@@ -565,17 +613,17 @@ To add the example library (assumed to be in /usr/local/lib) to the DHCPv4
|
|||||||
module, the following bindctl commands must be executed:
|
module, the following bindctl commands must be executed:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
> config add Dhcp4/hook_library
|
> config add Dhcp4/hook_libraries
|
||||||
> config set Dhcp4/hook_library[0]/name "/usr/local/lib/example.so"
|
> config set Dhcp4/hook_libraries[0] "/usr/local/lib/example.so"
|
||||||
> config commit
|
> config commit
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The DHCPv4 server will load the library and execute the callouts each time a
|
The DHCPv4 server will load the library and execute the callouts each time a
|
||||||
request is received.
|
request is received.
|
||||||
|
|
||||||
@section hookAdvancedTopics Advanced Topics
|
@section hooksdgAdvancedTopics Advanced Topics
|
||||||
|
|
||||||
@subsection hookContextCreateDestroy Context Creation and Destruction
|
@subsection hooksdgContextCreateDestroy Context Creation and Destruction
|
||||||
|
|
||||||
As well as the hooks defined by the server, the hooks framework defines
|
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
|
two hooks of its own, "context_create" and "context_destroy". The first
|
||||||
@@ -585,14 +633,14 @@ to initialize per-request context. The second is called after all
|
|||||||
server-defined hooks have been processed, and is to allow a library to
|
server-defined hooks have been processed, and is to allow a library to
|
||||||
tidy up.
|
tidy up.
|
||||||
|
|
||||||
As an example, the v4_lease_write
|
As an example, the v4_lease_write example above required that the code
|
||||||
example above required that the code check for an exception being
|
check for an exception being thrown when accessing the "hwaddr" context
|
||||||
thrown when accessing the "hwaddr" context item in case it was not set.
|
item in case it was not set. An alternative strategy would have been to
|
||||||
An alternative strategy would have been to provide a callout for the
|
provide a callout for the "context_create" hook and set the context item
|
||||||
"context_create" hook and set the context item "hwaddr" to an empty
|
"hwaddr" to an empty string. Instead of needing to handle an exception,
|
||||||
string. Instead of needing to handle an exception, v4_lease_write would
|
v4_lease_write would be guaranteed to get something when looking for
|
||||||
be guaranteed to get something when looking for the hwaddr item and so
|
the hwaddr item and so could write or not write the output depending on
|
||||||
could write or not write the output depending on the value.
|
the value.
|
||||||
|
|
||||||
In most cases, "context_destroy" is not needed as the Hooks system
|
In most cases, "context_destroy" is not needed as the Hooks system
|
||||||
automatically deletes context. An example where it could be required
|
automatically deletes context. An example where it could be required
|
||||||
@@ -600,32 +648,143 @@ 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
|
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
|
destruction of the context, that memory will not be automatically
|
||||||
released. Freeing in the memory in the "context_destroy callout will solve
|
released. Freeing in the memory in the "context_destroy callout will solve
|
||||||
that problem. (Actually, when the context is destroyed, the destructor
|
that problem.
|
||||||
|
|
||||||
|
Actually, when the context is destroyed, the destructor
|
||||||
associated with any objects stored in it are run. Rather than point to
|
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
|
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.
|
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,
|
When the context is destroyed, the smart pointer's destructor is run,
|
||||||
which will automatically delete the pointed-to object.)
|
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.
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
The requirement for the context_destroy callout can be eliminated if
|
||||||
|
a Boost shared ptr is used to point to the allocated memory:
|
||||||
|
|
||||||
|
@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.
|
||||||
|
@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.)
|
||||||
|
|
||||||
|
|
||||||
@subsection hookCalloutRegistration Registering Callouts
|
@subsection hooksdgCalloutRegistration Registering Callouts
|
||||||
|
|
||||||
As briefly mentioned in @ref hookExampleCallouts, the standard is for
|
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
|
callouts in the user library to have the same name as the name of the
|
||||||
to which they are being attached. This was followed in the tutorial, e.g.
|
hook to which they are being attached. This convention was followed
|
||||||
the callout that needed to be attached to the "pkt_rcvd" hook was named
|
in the tutorial, e.g. the callout that needed to be attached to the
|
||||||
pkt_rcvd.
|
"pkt_rcvd" hook was named pkt_rcvd.
|
||||||
|
|
||||||
The reason for this standard is that when the library is loaded, the
|
The reason for this convention is that when the library is loaded, the
|
||||||
hook framework automatically searches the library for functions with the
|
hook framework automatically searches the library for functions with
|
||||||
same names as the server hooks. When it finds one, it attaches it to
|
the same names as the server hooks. When it finds one, it attaches it
|
||||||
that hook point. This simplifies the loading process and bookkeeping
|
to the appropriate hook point. This simplifies the loading process and
|
||||||
required to create a library of callouts.
|
bookkeeping required to create a library of callouts.
|
||||||
|
|
||||||
However, the hooks system is flexible in this area: callouts can have
|
However, the hooks system is flexible in this area: callouts can have
|
||||||
non-standard names, and multiple callouts can be registered on a hook.
|
non-standard names, and multiple callouts can be registered on a hook.
|
||||||
|
|
||||||
@subsubsection hookLibraryHandle The LibraryHandle Object
|
@subsubsection hooksdgLibraryHandle The LibraryHandle Object
|
||||||
|
|
||||||
The way into the part of the hooks framework that allows callout
|
The way into the part of the hooks framework that allows callout
|
||||||
registration is through the LibraryHandle object. This was briefly
|
registration is through the LibraryHandle object. This was briefly
|
||||||
@@ -642,11 +801,11 @@ The LibraryHandle provides three methods to manipulate callouts:
|
|||||||
|
|
||||||
The following sections cover some of the ways in which these can be used.
|
The following sections cover some of the ways in which these can be used.
|
||||||
|
|
||||||
@subsubsection hookNonstandardCalloutNames Non-Standard Callout Names
|
@subsubsection hooksdgNonstandardCalloutNames Non-Standard Callout Names
|
||||||
|
|
||||||
The example in the tutorial used standard names for the callouts. As noted
|
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
|
above, it is possible to use non-standard names. Suppose, instead of the
|
||||||
callout names "pkt_rcvd" and "v4_lease_write", we had named out callouts
|
callout names "pkt_rcvd" and "v4_lease_write", we had named our callouts
|
||||||
"classify" and "write_data". The hooks framework would not have registered
|
"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
|
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
|
do this is the "load" framework function, and its code would have had to
|
||||||
@@ -670,7 +829,7 @@ It is possible for a library to contain callouts with both standard and
|
|||||||
non-standard names: ones with standard names will be registered automatically,
|
non-standard names: ones with standard names will be registered automatically,
|
||||||
ones with non-standard names need to be registered manually.
|
ones with non-standard names need to be registered manually.
|
||||||
|
|
||||||
@subsubsection hookMultipleCallouts Multiple Callouts on a Hook
|
@subsubsection hooksdgMultipleCallouts Multiple Callouts on a Hook
|
||||||
|
|
||||||
The BIND 10 hooks framework allows multiple callouts to be attached to
|
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
|
a hook point. Although it is likely to be rare for user code to need to
|
||||||
@@ -684,16 +843,16 @@ LibraryHandle::registerCallout multiple times on the same hook, e.g.
|
|||||||
libhandle.registerCallout("pkt_rcvd", write_data);
|
libhandle.registerCallout("pkt_rcvd", write_data);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The hooks framework will call the callouts in the order they are registered.
|
The hooks framework will call the callouts in the order they are
|
||||||
The same CalloutHandle is passed between them, so any change made to the
|
registered. The same CalloutHandle is passed between them, so any
|
||||||
CalloutHandle's arguments or per-request context by the first is visible
|
change made to the CalloutHandle's arguments, "skip" flag, or per-request
|
||||||
to the second.
|
context by the first is visible to the second.
|
||||||
|
|
||||||
@subsubsection hookDynamicRegistration Dynamic Registration and Reregistration of Callouts
|
@subsubsection hooksdgDynamicRegistration Dynamic Registration and Reregistration of Callouts
|
||||||
|
|
||||||
The previous sections have dealt with callouts being registered during
|
The previous sections have dealt with callouts being registered during
|
||||||
the call to "load". The hooks framework is more flexible than that
|
the call to "load". The hooks framework is more flexible than that
|
||||||
in that callouts and be registered and deregistered within a callout.
|
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
|
In fact, a callout is able to register or deregister itself, and a callout
|
||||||
is able to be registered on a hook multiple times.
|
is able to be registered on a hook multiple times.
|
||||||
|
|
||||||
@@ -716,7 +875,11 @@ int pkt_rcvd(CalloutHandle& handle) {
|
|||||||
|
|
||||||
// Classify it.
|
// Classify it.
|
||||||
if (sum % 4 == 0) {
|
if (sum % 4 == 0) {
|
||||||
// Interesting, register the callback to log the data.
|
// 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);
|
handle.getLibraryHandle().registerCallout("v4_lease_write", write_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,7 +921,7 @@ int write_data(CalloutHandle& handle) {
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Note that the above example used a non-standard name for the callout
|
Note that the above example used a non-standard name for the callout
|
||||||
that wronte the data. Had the name been a standard one, it would have been
|
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,
|
registered when the library was loaded and called for the first request,
|
||||||
regardless of whether that was defined as "interesting". (Although as
|
regardless of whether that was defined as "interesting". (Although as
|
||||||
callouts with standard names are always registered before "load" gets called,
|
callouts with standard names are always registered before "load" gets called,
|
||||||
@@ -768,15 +931,14 @@ callout in the "load" function.)
|
|||||||
|
|
||||||
@note Deregistration of a callout on the hook that is currently
|
@note Deregistration of a callout on the hook that is currently
|
||||||
being called only takes effect when the server next calls the hook.
|
being called only takes effect when the server next calls the hook.
|
||||||
To illustrate this, suppose the callouts attached to a hook are A,
|
To illustrate this, suppose the callouts attached to a hook are A, B and C
|
||||||
B and C (in that order), and during execution, A deregisters B and C
|
(in that order), and during execution, A deregisters B and C and adds D.
|
||||||
and adds D. When callout A returns, B and C will still run. The next
|
When callout A returns, B and C will still run. The next time the server
|
||||||
time the server calls the callouts attached to the hook, callouts
|
calls the hook's callouts, A and D will run (in that order).
|
||||||
A and D will run (in that order).
|
|
||||||
|
|
||||||
@subsection hookMultipleLibraries Multiple User Libraries
|
@subsection hooksdgMultipleLibraries Multiple User Libraries
|
||||||
|
|
||||||
As alluded to in the section @ref hookConfiguration, BIND 10 can load
|
As alluded to in the section @ref hooksdgConfiguration, BIND 10 can load
|
||||||
multiple libraries. The libraries are loaded in the order specified in
|
multiple libraries. The libraries are loaded in the order specified in
|
||||||
the configuration, and the callouts attached to the hooks in the order
|
the configuration, and the callouts attached to the hooks in the order
|
||||||
presented by the libraries.
|
presented by the libraries.
|
||||||
@@ -818,7 +980,7 @@ It is stressed that the context for callouts associated with different
|
|||||||
libraries is entirely separate. For example, suppose "authorize" sets
|
libraries is entirely separate. For example, suppose "authorize" sets
|
||||||
the CalloutHandle's context item "foo" to 2 and "logpkt" sets an item of
|
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
|
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
|
item "foo", it gets a value of 2; when "validate" accesses an item of
|
||||||
the same name, it gets the value "bar".
|
the same name, it gets the value "bar".
|
||||||
|
|
||||||
It is also stressed that all this context exists only for the life of the
|
It is also stressed that all this context exists only for the life of the
|
||||||
@@ -831,7 +993,7 @@ 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
|
may be present, but will not affect the context values set by a library's
|
||||||
callouts.
|
callouts.
|
||||||
|
|
||||||
@subsection hookInterLibraryData Passing Data Between Libraries
|
@subsection hooksdgInterLibraryData Passing Data Between Libraries
|
||||||
|
|
||||||
In rare cases, it is possible that one library may want to pass
|
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
|
data to another. This can be done in a limited way by means of the
|
||||||
@@ -850,7 +1012,7 @@ 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.
|
a name will conflict with any existing or future BIND 10 argument names.
|
||||||
|
|
||||||
|
|
||||||
@subsection hookRegisterMultipleLibraries Dynamic Callout Registration and Multiple Libraries
|
@subsection hooksdgRegisterMultipleLibraries Dynamic Callout Registration and Multiple Libraries
|
||||||
|
|
||||||
On a particular hook, callouts are called in the order the libraries appear
|
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
|
in the configuration and, within a library, in the order the callouts
|
||||||
|
Reference in New Issue
Block a user