[ Next Article |
Previous Article |
Book Contents |
Library Home |
Legal |
Search ]
Communications Programming Concepts
DHCP Server API
The DHCP Server allows administrators and third parties to develop modules to be linked to the DHCP Server and be called at specific checkpoints throughout the processing of a DHCP or BOOTP message.
This API specifies the routines, their prototypes, and the desired function of each symbol to be exported by the user-defined module. Additionally, this document mentions the structures used by the DHCP server and any User-Defined Object and the symbols exported by the DHCP server as utilities to the API Programmer.
General
It is noted that security and performance degredation may be introduced by any User-Defined Object.
Because the DHCP server is run with root user authority, special care should be taken to ensure no security vulnerabilities are introduced by the User-Defined Object. This includes taking steps to protect against buffer overrun exploitations, and every possible security measure when writing to temporary files on the disk or executing system commands.
Also, as many of the routines that can be defined by the User Object are executed during the normal processing path of each DHCP client's message, care should be taken to not slow the possible response to the DHCP client.
Configuration
A User-Defined Object can be referenced and loaded by the DHCP server if specified in the configuration file with the "UserObject" configuration line or stanza. For example:
UserObject myobject
or
UserObject myobject
{
file /tmp/myobject.log;
}
In both cases, the dynamically loadable shared object "myobject.dhcpo" will be loaded from the /usr/sbin directory. In the second case, the object's Initialize() routine will be passed a file pointer as it is the responsibility of the object to parse and handle its own configuration stanza.
Structures
dhcpmsg
struct dhcpmsg
{
uint8_t op;
uint8_t htype;
uint8_t hlen;
uint8_t hops;
uint32_t xid;
uint16_t secs;
uint16_t flags;
uint32_t ciaddr;
uint32_t yiaddr;
uint32_t siaddr;
uint32_t giaddr;
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
uint8_t options[1];
};
dhcpmsg defines the structure and fields of the basic DHCP message. The options field is variable in length and every routine referencing a DHCP message will also specify the total length of the message.
dhcpoption
struct dhcpoption
{
uint8_t code;
uint8_t len;
uint8_t data[1];
};
dhcpoption defines the framework of a DHCP option encoded in its type, length, data format.
dhcpclientid
struct dhcpclientid
{
uint8_t type;
uint8_t len;
uint8_t id[64];
};
dhcpclientid uniquely identifies a DHCP client. It either defines the DHCP Client Identifier Option or it is created from the hardware type, hardware length, and harware address of a DHCP or BOOTP message that does not contain a Client Identifier Option. Both the DHCP message option and client identifier references will always point to network byte-ordered data.
dhcplogseverity
enum dhcplogseverity
{
dhcplog_syserr = 1 ,
dhcplog_objerr ,
dhcplog_protocol ,
dhcplog_warning ,
dhcplog_event ,
dhcplog_action ,
dhcplog_info ,
dhcplog_accounting ,
dhcplog_stats ,
dhcplog_trace
};
The enumerated type dhcplogseverity is used to indicate to the DHCP server what log severity should be used when displaying a User-Defined Object's error message to the DHCP server's log file through the exported routine dhcpapi_logmessage(). The severity must be enabled for logging for the message to be displayed.
Routines
A few requirements exist to conform to this API. The User-Defined Object MUST:
- provide the initialization routine, Initialize().
- provide the shutdown routine, Shutdown().
- provide at least one of the checkpoint functions defined in the API.
- NEVER alter any data given through reference to the routine when the reference is a "const" pointer.
Required Routines
Initialize
int Initialize ( FILE *fp,
caddr_t *hObjectInstance ) ;
|
Parameter |
Meaning |
fp |
An open FILE pointer in which the next line to be read is the configuration block for the UserObject that is loaded. The pointer will be NULL if no configuration
block exists following the UserObject definition in the DHCP Server configuration file. |
hObjectInstance |
To be set by the loaded object if the object requires private data to be returned to it through each invocation. A handle is created per
configuration instance of the loaded object, not once per the loading of the object. |
|
Return |
Meaning |
0 (zero) |
Object instance is successfully
initialized. The server should continue
to link to each symbol. |
!= 0 (non-zero) |
Object instance failed to initialize.
The server can free its resources and continue
to load, ignoring this section of the
configuration file. |
|
This routine must be defined by the object to be loaded by the server.
It is used each time the server is started, including restarts, and
is called each time the object is referenced in the DHCP server's
configuration file. It is not a requirement that the Initialize()
routine set the hObjectInstance handle. However, it is required
that the routine return a zero if successful and a non-zero if failure.
Failure indicates that the object's checkpoint routines cannot and will
not be used by the server.
If the file pointer, fp, is not NULL, its initial value references the first line of contained data within the configuration block of the User-Defined Object. Parsing should only continue to as far as an unmatched } (close brace) is read, as this indicates the end of the configuration block.
|
Shutdown
void Shutdown ( caddr_t hObjectInstance ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
|
This routine is called prior to the shutdown of the server and prior
to reloading the configuration file at each reinitialization of the
server. It should be used to deallocate all data allocated on an
initialization including the destruction of any threads created
during initialization. Execution must be returned to the server
or the server will fail to reinitialize and properly shut down. |
Checkpoint Routines
Only one of the following routines must be implemented by the Extension Object.
messageReceived
int messageReceived ( caddr_t hObjectInstance,
struct dhcpmessage **inMessage,
size_t *messageSize,
const struct in_addr *receivingIP,
const struct in_addr *destinationIP,
const struct in_addr *sourceIP ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
inMessage |
Points to the incoming DHCP or BOOTP
message, unaltered. |
messageSize |
Total length, in bytes, of the received
DHCP or BOOTP message. |
receivingIP |
Interface IP address receiving the
DHCP or BOOTP message. |
destinationIP |
Destination IP address taken from the
IP header of the received DHCP or BOOTP
message. |
sourceIP |
Source IP address taken from the IP
header of the received DHCP or BOOTP message.
|
|
Return |
Meaning |
0 (zero) |
The received message can continue
to be parsed and the client possibly offered
or given an address through the regular means
of the DHCP server. |
!= 0 (non-zero) |
It is determined that the source client
of this message not be given any response
from this server. The server will remain
silent to the client. |
|
The messageReceived() routine is a mechanism through which the
programmer can add an external means of authentication to each received
DHCP or BOOTP message. It is called just as the message is received
by the protocol processor prior to any parsing of the message.
The routine is passed not only the message itself
but three IP addresses in addition; these addresses used together
can determine whether the client is on a locally attached network, a remotely
routed network, and whether the server is receiving a broadcast message.
Additionally, the programmer has the ability to alter the received message,
but because this directly affects the remainder of message processing,
great care should be taken to only use this ability in rare and well-
understood occasions. |
addressOffered
void addressOffered ( caddr_t hObjectInstance,
const struct dhcpclientid *cid,
const struct in_addr *addr,
const struct dhcpmessage *outMessage,
size_t messageSize ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
cid |
The client identifier of the client. |
addr |
The address to be offered to the
client. |
outMessage |
The outgoing message ready to be sent
to the client. |
messageSize |
The length, in bytes, of the outgoing
message ready to be sent to the client. |
|
The addressOffered() routine is called with DHCP clients are
ready to be sent an address OFFER message. Its main purpose is to
be used for accounting as all the parameters only given to the
routine Read-Only, and the routine has no return code to prevent the
outgoing message to be sent.
|
addressAssigned
void addressAssigned ( caddr_t hObjectInstance,
const struct dhcpclientid *cid,
const struct in_addr *addr,
const char *hostname,
const char *domain,
const struct dhcpmessage *outMessage,
size_t messageSize ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
cid |
The client identifier of the client. |
addr |
The address selected for the client. |
hostname |
The hostname which was or should have
been associated with the client. |
domain |
The domain in which the hostname for
the client was or should have been be
updated. |
outMessage |
The outgoing message ready to be sent
to the client. |
messageSize |
The length, in bytes, of the outgoing
message ready to be sent to the client. |
|
The addressAssigned() routine is called after the database has
associated the address with the client and just prior to sending the
BOOTP response or DHCP ACK to the client. If configured, a DNS update
has already been queued or has already occured.
This routine can be used for accounting purposes or to add an external
means of name and address association. The hostname and domain
arguments are selected based upon the A record proxy update policy
and the append domain policy (configured in the db_file database
through the keywords proxyARec and appendDomain,
respectively), as well as the defined and suggested hostname and domain
options for the client.
All parameters are offered to the user-defined routine as Read-Only,
and no return value is presented as a means of preventing the address
and client binding. |
address Released
void addressReleased ( caddr_t hObjectInstance,
const struct dhcpclientid *cid,
const struct in_addr *addr,
const char *hostname,
const char *domain ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
cid |
The client identifier of the client. |
addr |
The address previously in use by the
client. |
hostname |
The hostname previously associated by
the server with this client and address
binding. |
domain |
The domain in which the hostname for
the client was previously or should have
previously been updated. |
|
The addressReleased() routine is called when DHCP clients are
ready to be sent an address OFFER message. Its main purpose is to
be used for accounting as all the parameters are only given to the
routine Read-Only. The routine is called just after the database has
been instructured to disassociate the client identifier and address
binding, and if configured, after the DNS server has been indicated
to disassociate the name and address binding. |
addressExpired
void addressExpired ( caddr_t hObjectInstance,
const struct dhcpclientid *cid,
const struct in_addr *addr,
const char *hostname,
const char *domain ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
cid |
The client identifier of the client. |
addr |
The address previously in use by the
client. |
hostname |
The hostname previously associated by
the server with this client and address
binding. |
domain |
The domain in which the hostname for
the client was previously or should have
previously been updated. |
|
The addressExpired() routine is called when any DHCP database
has determined that the address and client identifier association
has existed beyond the end of any offered lease, and therefore
the association has been canceled. Its main purpose is to
be used for accounting as all the parameters are only given to the
routine Read-Only. |
addressDeleted
void addressDeleted ( caddr_t hObjectInstance,
const struct dhcpclientid *cid,
const struct in_addr *addr,
const char *hostname,
const char *domain ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
cid |
The client identifier of the client. |
addr |
The address previously in use by the
client. |
hostname |
The hostname previously associated by
the server with this client and address
binding. |
domain |
The domain in which the hostname for
the client was previously or should have
previously been updated. |
|
The addressDeleted() routine is called when any address association
is explicitly deleted without any interaction from the client or because
of any lease expiration. The most common cases in which this routine will
be invoked include the reinitialization of the DHCP server, when
realizing a new configuration may cause a previous client and address
association to become invalid, and when the administrator explicitly
deletes an address by using the dadmin command.
Its main purpose is to be used for accounting as all the parameters
are only given to the routine Read-Only. |
addressDeclined
void addressDeclined ( caddr_t hObjectInstance,
const struct dhcpclientid *cid,
const struct in_addr *addr,
const char *hostname,
const char *domain ) ;
|
Parameter |
Meaning |
hObjectInstance |
The configuration instance handle created
when this object was initialized. |
cid |
The client identifier of the client. |
addr |
The address that was declined by the
client. |
hostname |
The hostname previously associated by
the server with this client and address
binding. |
domain |
The domain in which the hostname for
the client was previously or should have
previously been updated. |
|
The addressDeclined() routine is used when a DHCP client
indicates to the server that the given address is in use on the network.
The DHCP client does this through the DHCP DECLINE message type.
The main purpose of this routine is to be used for accounting
as all the parameters are only given to the routine Read-Only.
The routine is called just after the database has
been instructured to disassociate the client identifier and address
binding, and if configured, after the DNS server has been indicated
to disassociate the name and address binding. |
Exported Routines
The following routine is available to the user-defined
object programmer. The prototype is available in <dhcpapi.h>
with the symbol defined for linking in /usr/lib/dhcp_api.exp.
dhcpapi_logmessage
void dhcpapi_logmessage ( enum dhcplogseverity s,
char *format,
... ) ; |
Parameter |
Meaning |
s |
Severity of the message to be logged.
Message severities are defined in the
dhcpapi.h header file and correspond
directly to the DHCP server configuration
logItem levels of logging. |
format |
Typical printf() format string. |
|
Specifies a message to be logged to the DHCP server's configured log
file. The message severity specified by the s parameter must
be enabled in the logging configuration of the server for the message
will not be displayed. |
[ Next Article |
Previous Article |
Book Contents |
Library Home |
Legal |
Search ]