cc/td/doc/product/rtrmgmt/ciscoasu/nr/nr3-5
hometocprevnextglossaryfeedbacksearchhelp
PDF

Table of Contents

Extension Points

Extension Points

You can write extensions to affect the way Network Registrar's DHCP server handles requests, the way it responds to requests, and to change the behavior of Network Registrar after an extension is run.

Creating Extensions

You can alter and customize the operation of the Network Registrar DHCP server through the use of extensions, which are programs that you can write in either Tcl or C/C++.

There are several steps in the creation of an extension for use in the DHCP server:

Determining the Task

The task is usually some modification of the behavior of the DHCP server's processing so that it better meets the needs of your environment.

For example, suppose you have an unusual routing hub that uses BOOTP for its configuration. This device, however, sends out a BOOTP request with an Ethernet hardware type (that is, 1) and a particular MAC address in the chaddr field. It then sends out another BOOTP request with a hardware type of Token Ring (that is, 6), and the same MAC address in the chaddr field.

Specifying two different hardware types causes the DHCP server to allocate two IP addresses to the device since the DHCP server distinguishes between a MAC address with hardware type of 1 and a hardware type of 6---to the DHCP server these are different devices.

In this case, write an extension that prevents the DHCP server from handing out two different addresses to the same device.

Deciding on the Approach

There are often many solutions to a single problem. When choosing the type of extension to write, you should first consider rewriting the input DHCP packet. This is a good approach, because it avoids any need for knowledge of the internal processing of the DHCP server.

You could solve the problem of the two IP addresses in two different ways:

This example illustrates a second useful approach to modifying the DHCP server's behavior---rewriting the DHCP response packet just before it is returned to the DHCP client.

One reason to use extensions is to transmit information available only within the DHCP server to the external environment. The extension point that you can use for this purpose is the post-send-packet, which is called after the transmission of any DHCP response packet to a DHCP client.

Choosing the Extension Point

To decide on the appropriate extension point to perform the task, you have to understand how the DHCP server processes client requests and generates DHCP responses.

The example task uses the first extension point after the DHCP server receives the request packet (post-packet-decode), and the last extension point before the DHCP server transmits the response packet to the DHCP client (pre-packet-encode).

Choosing the Extension Language

You can write extensions in Tcl or in C/C++. The capabilities of each language (as far as the DHCP server is concerned) are similar, although the API is slightly different to support the two approaches to language design.

Choosing Tcl allows you to write an extension quickly with less difficulty. If the extension is short, then the interpreted nature of Tclwill not have a serious affect on the performance. When you write an extension in Tcl, you are less likely to introduce a bug that will crash the server.

Choosing to write the extension in C/C++, provides the maximum possible performance and flexibility---including communicating with external processes. Since the complexity of the C/C++ API is greater, the possibility of a bug in the extension crashing the server is more likely to happen.

Language-Independent API

You need to be aware of the following items independent of whether you choose to write your extensions in Tcl or C/C++.

Routine Signature

You need to define the extension to the DHCP server as a file and a routine within that file. You then need to attach the extension to one or more of the DHCP server extension points. When the DHCP server reaches that extension point, it calls the routine defined by the extension. When this routine returns, the return defines success or failure. You can configure the DHCP server to drop a packet on the failure of an extension.

You can configure one file (Tcl source file or C/C++ .dll or .so file) as multiple extensions to the DHCP server by specifying a different entry point for each configured extension.

The DHCP server calls every routine entry point with at least three arguments---these are three dictionaries (request, response, and environment). Each dictionary is a representation of a key-value pair. The extension can retrieve specific data items from the DHCP server by performing a get method on a dictionary for a particular data item. The extension can alter data items by performing a put operation on the same named data item. Although you cannot use all dictionaries at every extension point, the calling sequence for all routines is the same for every extension point. (The extension encounters an error if it attempts to reference a dictionary that is not present at a particular extension point.)

Dictionaries

Use the environment dictionary to communicate between two extensions running at different extension points. When the first extension point (at which some extension is configured) is encountered, the DHCP server creates an environment dictionary. The environment dictionary is the only dictionary in which the names of the allowable data items are not fixed by the DHCP server. It allows an extension to insert any string-valued data item. Every extension point in the flow of control between the request and response for the DHCP client (that is, all of the extension points except pre-dns-add-forward), share the same environment dictionary. Thus, an extension may determine that some condition exists and place a sentinel in the environment dictionary so that a subsequent extension can avoid determining that the same condition.

In the previous example, the extension at the post-packet-decode extension point determines that the packet was the interesting one---from a particular manufacturer's device, BOOTP, and Token Ring, and then rewrites the hardware type from Token Ring to Ethernet. It also places a sentinel in the environment dictionary, and then a very simple extension at the pre-packet-encode extension point rewrites the hardware type back to Token Ring.

Utility Methods

Each dictionary has associated utility methods that include the ability to reset the trace-level for an extension, and log values into the output file.

Init-Entry

There is an additional extension point that is called whenever the DHCP server configures or unconfigures the extension. This occurs whenever the DHCP server is started or stopped. (Note that a reload is a stop and then a start.) This entry point has the same signature as the other entry points for the extension, but you can only use the environment dictionary at this extension point. You do not configure the init-entry extension point with the nrcmd dhcp attachExtension command, but rather you configure it implicitly by defining an init-entry on an already configured extension.

In addition to configuring an init-entry with the name of the init-entry point, you can also configure a string of arguments that the DHCP server loads in the environment dictionary under the string arguments prior to calling the init-entry point. Using arguments allows you to create an extension that can be customized by giving it different init arguments and thus not requiring a change to the code to elicit different behavior. You configure arguments by setting init-args on an existing extension point.

These arguments are present for both the configure and unconfigure calls of the init-entry entry point. The extension-point name for the configure call is initialize, and for the unconfigure call is uninitialize.

Configuration Errors

There are many reasons why an extension can fail to configure: the file may not be found, the entry point or init-entry point may not appear in the file, or the extension itself can return failure from an init-entry call. If the extension returns failure from an init-entry, the extension will fail to configure.

By itself a failure for an extension to configure is not fatal, and will not prevent the DHCP server from starting. If, however, the server tries to configure an extension point using the extension that failed, the configuration for that extension point will fail. If the DHCP server fails to configure any extension points, then the server will not start. Therefore, in order to debug the configuration process, you can configure your extension and the init-entry point without attaching it to an extension point. When you have completed this process, you can attach your extension to an extension point.

Recognizing Extensions

The DHCP server only recognizes extensions when it initially configures itself---at start or reload time. Thus, you can change an extension, or the configuration for extensions in general, but not until you have reloaded or restarted the server the changes have no effect. Forgetting to reload the DHCP server can be a frequent source of errors while debugging extensions.

The reason Network Registrar requires a reload is to ensure minimum processing impact by preloading extensions and getting them ready at server configuration time. While this approach is useful in production mode, it might cause some frustration when you are debugging extensions.

Tcl Extensions

If you choose to write your extensions in Tcl, you should understand the Tcl API, how to handle errors and boolean variables, and how to initialize Tcl extensions.

Tcl API

Every Tcl extension has the same routine signature:

	proc yourentry { request response environ } {
	#your code goes here
}
 

In order to operate on the data items in any dictionary, you must treat these arguments as commands. Thus, to get the giaddr of the input packet, you would write:

set my_giaddr [ $request get giaddr ]
 

This sets the Tcl variable my_giaddr to the string value of the giaddr in the packet (for example, "10.10.1.5" or "0.0.0.0").

You could rewrite the giaddr in the input packet by using the Tcl statement:

	$request put giaddr "1.2.3.4"
 

In order to allow one routine entry to be configured for multiple different extension points and to alter its behavior depending on the extension point from which it is called, the ASCII name of the extension point is passed in the environment dictionary under the key extension-point.

Example Tcl Extensions

For sample Tcl extensions, see the Network Registrar directory:

Dealing with Tcl errors

Remember that you will generate a Tcl error if you reference a dictionary that is not available; if you reference a dictionary data item that is not available; or if you request a put operation on an invalid data item (for example, an IP address of "1.2.3.a" is not acceptable).

In these cases, the extension immediately fails unless you surround the statement with a catch { } error statement:

	catch { $request put giaddr "1.2.3.a" } error

Handling Boolean Variables

In the environment dictionary, the boolean variables are string-valued and have a value of true or false, and the DHCP server expects an extension to set the value to true or false.

In the request or response dictionaries however, boolean values are single-byte numeric format, where true is a 1 and false is a 0. While more efficient for the C/C++ extensions, this approach does make the Tcl API a bit more complex.

Configuring Tcl Extensions

To configure an extension, write the extension and place it in the extensions directory.

/opt/nwreg2/extensions/dhcp/tcl
Program Files\Network Registrar\extensions\dhcp\tcl.

When the DHCP server configures a Tcl extension during startup, it reads the Tcl source file into a Tcl interpreter. Any syntax errors that appear in the source file will cause the Tcl interpreter to be unable to load the file since the DHCP server will fail to configure the extension. Typically, the DHCP server will generate an error traceback in the log file from Tcl to help you to determine the location of the error.

The Init-Entry Extension Point

Tcl extensions support the init-entry entry point, and the arguments supplied in the init-args parameter to the command line appear in the environment dictionary associated with the key arguments.

Multiple Tcl interpreters may be running within the DHCP server for performance, each in its own Tcl context. The Tcl extension will be called once at the init-entry point for every Tcl context (interpreter) running in the DHCP server. You should ensure that your Tcl extension's init-entry is coded to be robust given multiple calls.

There is no way for any information to be passed between the Tcl contexts, but the init-entry can initialize global Tcl variables in each Tcl context (interpreter) that can then be accessed by any Tcl extension regardless of the Tcl interpreter in which it runs.

Note that the Tcl interpreters are shared among all of the Tcl extensions, so if your Tcl extension initializes global variables or defines procedures, ensure that these do not conflict with some other Tcl extensions' global variables or procedure names.

C/C++ Extensions

All DHCP C/C++ extensions are called dex extensions, which is short for DHCP Extension.

C/C++ API

The routine signature for both the entry and init-entry routines for the C/C++ API is as follows:

typedef int (DEXAPI * DexEntryPointFunction)
int iExtensionPoint,
dex_AttributeDictionary_t* pRequest,
dex_AttributeDictionary_t* pResponse,
dex_EnvironmentDictionary_t* pEnviron );
 

In addition to pointers to three structures, the integer value of the extension point is one of the parameters of each routine.

The C/C++ API has been specifically constructed so that you do not have to link your shared library with any Network Registrar DHCP server files. The entry to your routine is configured when the extension is configured, and then the necessary call-back information for the operations to be performed on the request, response, and environment dictionaries is supplied in the structures that comprise the three dictionary parameters passed to your extension routine.

The DHCP server returns all binary information in network order, which is not necessarily properly aligned for executing architecture.

Using Types

Many C/C++ routines available use types, for example, getByType(). These routines are designed for use in performance-sensitive environments. The reasoning behind these routines is that the extension can acquire pointers to types once, for example in the init-entry point, and thereafter use the pointers instead of string-valued names when calling the routines of the C/C++ API. Using types in this manner removes one hash-table lookup from the extension processing flow of execution, which should improve (at least fractionally) the performance of any extension.

Building C/C++ Extensions

The directory (UNIX---/opt/nwreg2/examples/dhcp/dex and for NT---\Program Files\Network Registrar\examples\dhcp\dex) contains example C/C++ extension code, as well as a short Makefile that has been designed to build the example extensions. In order to build your own extensions, you need to modify this file. It has sections for Microsoft Visual C++ V5.0, GNU C++, and SunPro C++. Simply move the comment lines in order to configure the file for your environment.

Your extension needs to reference the include file dex.h. This file contains the information your program will need to utilize the C/C++ API. When building C/C++ extensions on NT, remember to add your entry points to the `.def' file.

After you build the .dll or .so file (all dex extensions are shared libraries), you need to move them into the (UNIX---/opt/nwreg2/examples/dhcp/dex and for NT---\Program Files\Network Registrar\examples\dhcp\dex) directory. You can then configure them.

Configuring C/C++ Extensions

Since the .dll and .so files are active when the server is running, it is not a good idea to overwrite them. After the server is stopped, the .dll and .so files are not in use and you can overwrite them with newer versions.

Debugging C/C++ Extensions

Because your C/C++ shared library runs in the same address space as the DHCP server, and receives pointers to information in the DHCP server, any bugs in your C/C++ extension can very easily corrupt the DHCP server's memory, leading to a server crash. For this reason, use extreme care when writing and testing a C/C++ extension. Frequently the approach to an extension should be tried with a Tcl extension. Then , when you have seen the operations performed and verified their effect on the DHCP server's behavior, you can recode the extension into C/C++ for increased performance.

Pointers into DHCP Server Memory

The C/C++ extension interface routines return pointers into DHCP server memory in two formats.

In both of these cases, the pointers into the DHCP server memory are valid for the duration of the execution of the extension running at that extension point. In addition, they are also valid for the rest of the extension points in the series processing this request. Thus, an abytes_t pointer returned in the post-packet-decode extension point is still valid in the post-send-packet extension point. It is not, however, valid in the pre-dns-add-forward extension point, because this extension point is not part of the cycle of request-response processing, but is handled by a different subsystem. In other words, the duration of validity of the pointers returned into DHCP server memory is the same as the duration of validity of information that is placed into the environment dictionary.

There is an exception to this statement. One C/C++ routine, getType, returns a pointer to an abytes_t that references a type. These pointers are valid through the entire life of the extension. Typically, you would call this routine in the init-entry extension point and save the pointers to the abytes_t structures that define the types in the static data of the shared library. Pointers to abytes_t structures returned by getType are valid from the init-entry call for the initialization until the init-entry call for uninitialization.

The Init-Entry Entry Point

The init-entry extension point is called once when each extension is configured and once when each extension is unconfigured.

The file dex.h defines two extension point values that are passed as the extension points for the configure and unconfigure calls: DEX_INITIALIZE for configure and DEX_UNINITIALIZE for unconfigure.

In addition, the environment dictionary value of the extension-point is initialize or uninitialize in each call.


hometocprevnextglossaryfeedbacksearchhelp
Posted: Thu Feb 3 10:44:40 PST 2000
Copyright 1989 - 2000©Cisco Systems Inc.