[  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 ]