Table of Contents

Name

dhcpd - DHCP and BootP Server

Synopsis

dhcpd [ -a log_assignments-level ] [ -A ] [ -b lastbindings-directory ] [ -B bindingsdumpfile ] [ -c chdir-path ] [ -C ] [ -d debuglevel ] [ -e ] [ -E so_rcvbuf ] [ -f ] [ -F ] [ -G group ] [ -h hostname ] [ -H|-I ] [ -L ] [ -m my_ip_addr ] [ -p snmp-port ] [ -P pidfile ] [ -R ] [ -s statisticsdumpfile ] [ -S ] [ -T ] [ -u ] [ -U user ] [ -x conffile ] [ bootptabfile [ bootptabdumpfile ] ]

Availability

CMU dhcpd 3.3.7 with the Princeton patches is available at: http://www.net.princeton.edu/software/dhcpd/.

Description

dhcpd is a BootP and DHCP server. It responds to BootP and DHCP clients, assigning to them IP addresses and providing other configuration information to these clients.

This manual page describes Carnegie Mellon University’s dhcpd (version 3.3.7) with the Princeton patches (patchlevel 12) installed.

This version of dhcpd attempts to conform to the the following Internet standards or draft standards: RFC951, RFC1534, RFC1542, RFC2131, RFC2132, draft-ietf-dhc-userclass-00.txt. Any known deviations between this server’s behavior and the behavior described in those documents appears in the BUGS section below.

WARNING: Only run this software on a network for which you are responsible. If you are not the person responsible for providing BootP and DHCP service on the network, do not run this software. Instead, talk with your network administrator. Running an inappropriate BootP or DHCP server on a network (e.g. any network that has other official BootP or DHCP servers) can break BootP and DHCP service for everyone on that network.

dhcpd should be started from your host’s startup scripts; it is not suitable for startup from inetd.

The server requires a a bootptab(5) file (by default /etc/bootptab), which contains an entry for each client, typically specifying the static IP address and other configuration information to return to the client. It also may contain IP addresses to be assigned dynamically to clients as needed. It may also contain entries for clients with no static IP address assigned, presumably for those clients that require only dynamic IP address assignment. The file is read when the server is started, and by default is re-read automatically whenever the file change.

The server requires a dhcpd.conf(5) file (by default /etc/dhcpd.conf), which contains a description of each of the server’s interfaces and the directly-attached networks. If your network contains BootP Relay Agents, it contains an entry for each BootP Relay Agent/remote network combination. If the server is to dynamically assign IP addresses on any networks, it contains an entry describing each of those network as well as the associated pool of dynamic IP addresses. It may contain some statements that tune the behavior of the server. The file is read when the server is started, and by default is re-read automatically whenever the file changes.

Although this implementation is designed to run on a server that has a single interface, it has (very limited) support for multihomed servers. See MULTIHOMED SERVERS below for more information.

This implementation can assign IP addresses statically to BootP and DHCP clients, similar to the way older BootP servers operated. It can also be configured to dynamically assign IP addresses from pools of available addresses to BootP and DHCP clients, possibly restricting these assignments based on whether the client’s Ethernet address (for BootP clients) or Client Identifier (for DHCP clients) is known, and/or whether the client is a BootP or a DHCP client.

In the absence of BootP Relay Agents, one host on each IP network is normally configured to run dhcpd. If you have multiple IP networks, you may use BootP Relay Agents (e.g. standalone, or embedded in your IP routers) to forward clients’ BootP and DHCP broadcasts to specific servers, obviating the need to run dhcpd on a host on every IP network.

You may run dhcpd on several hosts (on the same or different networks) for redundancy. See REDUNDANT SERVERS below for more information.

Options

-a log_assignments-level
Specifying a log_assignments-level of 1 causes the server to produce a message whenever it assigns an address to a client, suitable for parsing to produce reports. Specifying a log_assignments-level of 2 adds a message whenever it renews an existing DHCP lease. Specifying a log_assignments-level of 3 adds a message whenever it sends an offer for a DHCP lease.
-A
Disables the Check File Access feature. The Check File Access feature is enabled by default. (The default may be modified via a compile-time option.) For more information, see CHECK FILE ACCESS below.
-b lastbindings-directory
Specifies the lastbindings-directory that will be used to store each client’s most-recent binding. If not specified, this defaults to /etc/bindings. (The default may be modified via a compile-time option.) The directory must already exist and be writable by the server.
-B bindingsdumpfile
Specifies the name of the file to which the server will dump the current bindings and some packet statistics when it receives a SIGUSR2 signal. If left unspecified, it defaults to /tmp/bind.dump.
-c chdir-path
Sets the current working directory used by the server. If specified, this should be an absolute path, e.g. /tftpboot. If not specified, it defaults to /. (Note that if client bootfile names are specified as relative pathnames, and the server needs to check the existence or size of a bootfile, the bootfile pathname will be taken relative to the server’s current working directory.)
-C
adds some compact messages when debugging is turned on. These messages are most useful when you want some information about each packet seen, but don’t want to run at debuglevel 2 or higher.
-d debuglevel
Sets the debuglevel variable that controls the amount of debugging messages generated. For example, -d4 or -d 4 will set the debuglevel to 4. If unspecified, the debuglevel defaults to 0 (no debugging). For a summary of the types of messages produced at each debug level, see DEBUG LEVELS below. You can increase the debuglevel by sending the process a SIGABRT (SIGIOT) signal; you may reset the debuglevel to 0 by sending a SIGSYS signal (if available on your system).
-e
Specifies that a message should be logged whenever a lease is expired or otherwise removed. Without this option, such a message is only logged if the debuglevel is 4 or greater.
-E so_rcvbuf
Overrides the operating system’s default socket receive buffer size (SO_RCVBUF) with the value you specify. The value must be an integer. Running the program with a high enough debug level will display the default socket receive buffer size and the result of attempting to change it to the value you specify. You may want to increase this value if you believe the program is missing requests from clients that do not fit into this buffer; however, doing so might be counterproductive if the program takes so long to process these queued requests that clients must retransmit their requests. The operating system may impose an upper limit on this value. It probably doesn’t make sense to reduce this to less than the operating system’s default value.
-f
Specifies that the server should not fork, but instead remains in the foreground. Only use this when you are starting the server manually for debugging purposes. When in the foreground, any messages produced by the server are written to stderr instead of syslog. If you specify this option, it is best to specify it first, to avoid having any earlier messages directed to syslog.
-F
Enables the "Don’t Look for Default Bootfile" feature. When no bootfile is specified in the client’s request and the bootptab, the server normally looks for a local bootfile using a default filename. If you do not store bootfiles locally (or do not store any using the default filenames) checking for these files is wasted effort, Enable the "Don’t Look for Default Bootfile" feature to cause the server to not look for a local bootfile with a default filename when no bootfile is specified in the client’s request and the bootptab.
-G group
Specifies the effective groupname or gid the server should become after it completes startup operations. Only supported on systems with setegid(). See the -U option, and the RUNNING AS AN UNPRIVILEGED USER section below.
-h hostname
Specifies the server’s hostname, overriding the hostname normally obtained via uname(2). This hostname is what the server uses to match or fill in the sname field in request/response packets, when appropriate. The hostname is also used to determine the value of my_ip_addr (when the -m option is not specified).
-H
Specifies that the server should ignore a DHCP request when the request contains a DHCP Client Identifier option and its value does not match the htype and chaddr values in the request. This option may not be specified if the -I option is also specified, as -I causes the server to ignore the DHCP Client Identifier option. If your intent is that the server identify DHCP clients by htype and chaddr rather than by DHCP Client Identifier, then you should specify the -H option. Omitting it would cause the server to view all the requests from one device that uses a constant (htype, chaddr) but unique DHCP Client Identifiers as the same client, while the device would view the server’s responses as being intended for the multiple DHCP Client Identifiers.
-I
Specifies that the server should ignore any DHCP Client Identifier option specified in packets coming from DHCP clients. (As a result, the server will rely on the htype and chaddr fields to construct a Client Identifier for all DHCP clients.) This option may not be specified if the -H option is also specified, because the -H option implies the server must examine the DHCP Client Identifier option.
-L
Enables the Lone DHCP Server feature. For more information, see the LONE DHCP SERVER below.
-m my_ip_addr
Override the my_ip_addr value used internally by the server to indicate the server host’s own IP address. Normally my_ip_addr is computed by the server by looking up hostname (see below). You can instead force my_ip_addr to a fixed value using this option. This option should almost never be used; specifying an inappopriate value will cause the server (and clients) to malfunction. It may be helpful if the server host has a problem using gethostbyname(3), or if the server host has virtual interfaces (in concert with the -S option).
-p snmp-port
Specify the SNMP port on which to listen for SNMP requests; this server includes an SNMP agent that can be used to examine the server’s state and modify it. If unspecified, snmp-port defaults to 161. If the port is already in-use, you will receive a harmless "address already in use error" when the server tries to bind the snmp port at startup, and the server will locate another port for its SNMP listener. You can entirely disable the SNMP agent by specifying a port of 0. (This option is only usable if the optional SNMP support was included at compile-time; by default it is excluded.)
-P pidfile
Specifies the name of the file to which the server will write its process-id at startup. If left unspecified, it defaults to /etc/dhcpd.pid.
-R
Turns on the Allow ’Server IP Address’ Option in RENEWAL/REBINDING States feature. This feature attempts to compensate for some invalid DHCPREQUEST packets generated by some clients. See the ALLOW ’SERVER IP ADDRESS’ OPTION IN RENEWAL/REBINDING STATES section below.
-s statisticsdumpfile
Specifies the name of the file to which the server will dump some statistics when it receives a SIGWINCH signal. If left unspecified, it defaults to /tmp/dhcpd.statistics.
-S
Turns off the BOOTPREPLY siaddr Local Optimization feature; see below for more details. This may be helpful if the server host has virtual interfaces (in concert with the -m option).
-T
Enables the "Offer Terminates Unexpired Lease" feature. That feature is enabled by default starting in version 3.3.7+PU-11. Specifying this option disables the feature, resulting in the behavior seen in previous versions. For more details, see OFFER TERMINATES UNEXPIRED LEASE FEATURE below.
-u
Turns on the Renew Unbound Statics feature. This specifies that if a DHCP client attempts to renew a lease for a statically-assigned IP address, and the server does not believe this client presently has a lease for this IP address (but this client is assigned this static IP address in the bootptab(5) file), the server should go ahead and "renew" the lease, creating a new lease binding this client to this IP address. See the RENEW UNBOUND STATICS section below.
-U user
Specifies the effective username or uid the server should become after it completes startup operations. Only on systems with seteuid(). See the -G option, and the RUNNING AS AN UNPRIVILEGED USER section below.
-x conffile
Specifies the name of the configuration file for the daemon. Defaults to /etc/dhcpd.conf, although this default may be changed via a compile-time option. The format of this file is documented in dhcpd.conf(5).
bootptabfile
Specifies the name of the configuration file from which dhcpd loads its database of known clients and client options. Defaults to /etc/bootptab, although this default may be changed via a compile-time option. The format of this file is documented in bootptab(5).
bootptabdumpfile
Specifies the name of the file to which the server will dump its internal (parsed) version of the bootptab, when it receives a SIGUSR1 signal. If left unspecified, defaults to /tmp/bootpd.dump. (Because this is the second argument, in order to specify this argument you must also specify the preceeding argument, the bootptab file.)

Operation

When dhcpd is started it reads a bootptab(5) file (normally /etc/bootptab) that initializes the internal database of known clients and client options. It also reads a dhcpd.conf(5) file (normally /etc/dhcpd.conf) that tunes some of the server’s operational parameters, describes the server’s interfaces, describes legal BootP Relay Agents (if any), and describes networks receiving dynamic IP address assignment (if any). The information in both files is reloaded whenever the files change; the modification times are checked every time a packet is received. (You can also force a re-read by sending a SIGHUP signal to the server.)

During initialization, the server determine the UDP port numbers to be used by calling getservbyname(3) (which nomally uses /etc/services or NIS). Two service names (port numbers) are used:

     bootps - BootP and DHCP Server listening port
     bootpc - BootP and DHCP Client destination port

If the port numbers cannot be determined using getservbyname(3) then the values default to boopts=67 and bootpc=68.

The server determines its hostname via uname(2), although this may be overridden by the -h commandline option.

The server determines the value of my_ip_addr by looking up hostname using gethostbyname(3); it uses the first IP address returned. (You can instead specify a fixed value for my_ip_addr by using the -m option.)

The server uses my_ip_addr as the Server Identifier in DHCP response packets.

The server may also use my_ip_addr to fill in the siaddr field in some BOOTPREPLY packets. If an siaddr is specified via the bootptab (i.e. via the sa tag), that value is used to fill in siaddr. Otherwise, the server fills in siaddr with (one of) its own IP address(es); how it selects one depends on whether the client is locally-attached or non-local (based on examining the server’s interface addresses/netmasks). For a non-local client, the server fills in siaddr with my_ip_addr. For a local client, an optimization is introduced; the server fill in siaddr with the IP address of the server’s "closest" interface (based on examining its own interface addresses/netmasks). You can disable the latter optimization by specifying the -S option when starting the server; that turns off the BOOTPREPLY Local siaddr Optimization feature.

The value of my_ip_addr is also used in another situation. If a BootP or DHCP request packet’s giaddr field is 0, the server will pretend the packet’s giaddr field was actually my_ip_addr; i.e. the server will assume the packet arrived on the server’s interface that corresponds to my_ip_addr. This determines the IP network to which the server believes the client is attached, affecting the server’s selection of an appropriate IP address for the client.

The server makes a record of the IP address, network address, subnet mask, and broadcast address associated with each of the server’s interaces. (Interfaces are skipped if they are not UP or do not support BROADCAST. The LOOPBACK and any POINTTOPOINT interfaces are also skipped.)

Every client is identified by a unique Client Identifier (a.k.a. "clientid" or "cliid"). For BootP clients, this is chaddr, the value of the client hardware address field. For DHCP clients, this is normally the value of the Client Identifier option if the client specifies one, otherwise it is htype (the value of the client hardware type field) concatenated with chaddr (the value of the client hardware address field). You can force the server to always ignore any Client Identifier option specified by DHCP clients by specifying the -I option at startup; this may be useful if your clients sometimes specify garbage values for the Client Identifer option.

At startup, the server reads the information stored in the lastbindings directory to learn about the last binding that was recorded for each Client Identifier. It also uses this information to re-create a list of current bindings. Current bindings consist of those DHCP assignments that have not yet expired. They also include those BootP assignments for dynamically-assigned IP addresses. Any potential current binding that no longer appears valid (based upon the information in the configuration files) is not re-instated as a current binding. (BootP assignments for statically-assigned IP addresses are not stored as current bindings, as such assignments are stateless.)

At startup and whenever the server re-reads a changed bootptab or dhcpd.conf file, it examines all current bindings, and deletes those that no longer appear valid based on the new information.

Whenever the server assigns an IP address to a client, it updates its notion of this client’s lastbinding, a record of the most-recent assignment made to this Client Identifier. In addition to storing each lastbinding in-memory, they are also written out to the lastbindings directory, as this information must be preserved across server restarts. The writes to the lastbindings directory are cached and written to disk only periodically, by default every 30 seconds or 20 changes, whichever comes first. You can tune these parameters using the flushinterval and flushitems statements in the dhcpd.conf(5) file.

The lastbindings structure contains one record for each Client Identifier that the server has (ever) served; the record contains information about the most-recent binding assigned to that client. For efficiency, the records are stored in a binary form, in (no more than) 256 files, relying on a hash of the Client Identifier. Although only one record is stored per client (only its most-recent binding), the files in this directory will grow without bounds, as clients are never removed from this structure.

The server periodically performs garbage collection, to clean up its in-memory table of current bindings. During garbage collection, expired DHCP leases are removed. (These include both leases that a client has failed to renew, as well as offers that the client did not select; the latter look like 60-second leases.) (At this time, expiration of dynamically-assigned IP addresses provided to BootP clients is also performed if the Expire Infinite Dynamics feature is being used; see the relevant section below.) Garbage collection is normally performed every 30 seconds, but this can be tuned using the gcinterval statement in the dhcpd.conf(5) file.

The server stores a copy of its process-id in the /etc/dhcpd.pid file; the name of this file can be changed via a compile-time option.

You can force the server to dump a parsed version of its internal client database (the information obtained from the bootptab(5) file) to a file by sending it a SIGUSR1 signal. It dumps this information to the bootptabdumpfile specified on the commandline (defaults to /tmp/bootpd.dump). This is useful if you want to check that the server is parsing your bootptab(5) file the way you expect.

You can force the server to dump a snapshot of its current bindings (and some packet counts) to a file by sending it a SIGUSR2 signal. (The dump may also include some DHCP leases that have expired, as these are only removed from the current bindings during periodic garbage collection.) It dumps this information to the file /tmp/bind.dump.

When the server exits normally, it flushes any cached lastbinding changes to the lastbindings directory. To cause the server to exit normally, send it a SIGINT, SIGQUIT, or SIGTERM signal.

Output

The server can produce a variety of messages. These are normally sent to syslog with the program name "dhcpd". The syslog facility name defaults to LOG_DAEMON but may be changed via a compile-time option.

If you are running in the foreground (by starting with the -f option), server messages are also sent to stderr. (Startup messages produced before the -f option is parsed will not go to stderr, so it is best to specify -f as the first option if it is specified at all.)

By default, only serious server errors and the most serious problems parsing requests are reported. To see less-critical errors, or to follow the server’s handling of each request, increase the debuglevel with the -d commandline option or SIGABRT (SIGIOT) signal. Meaningful debuglevels range from 0 (the default) to 16; a summary of the kind of information that is added at each higher level appears in the DEBUG LEVELS section below.

Output sent to syslog vary from LOG_DEBUG or LOG_ERR levels. In general, messages indicating serious problems with the server itself or its databases are logged at LOG_ERR level. LOG_WARNING and LOG_NOTICE levels are used for unusual conditions which you may wish to look into. Most messages are at the LOG_NOTICE or LOG_INFO level, and the show the server in action. Messages logged at LOG_DEBUG are intended for server development.

If the server was made with the DEBUG compile-time option defined, then additional debugging messages appear when you set the debuglevel to 16 or above. Those additional messages are intended to help server developers locate problems in the server. As there is a runtime penalty if the executable was compiled with DEBUG defined (even when you run with debuglevel to 16 or above), you should only compile with DEBUG defined if you are really debugging the code.

If you specify the -a commandline option, the server will produce one line of output every time it assigns an IP address to client, in a form suitable for parsing to create reports. The message is produced the server actually assigns the IP address to a client, as opposed to when an address is simply offerred or renewed. Specifically, the message is produced when the server sends a BOOTPREPLY, or a DHCPACK in response to a client that is in the SELECTING or the INIT-REBOOT state. The message is also produced when the server sends a DHCPACK in response to a client that is in the RENEWING or REBINDING state if the address is being assigned due to the use of the "Renew Unbound Statics" feature (although the client is RENEWING or REBINDING, the server is actually creating a new address assignment). The message consists of the word "ASSIGNED" followed by the client’s protocol ("BOOTP" or "DHCP"), the IP address type ("STATIC" or "DYNAMIC"), the IP address assigned, the hostname associated with this IP address in parentheses, the words "TO CLIENT", the (possibly null) hostname associated with this client in parentheses, and an ASCII representation of the Client Identifier.

Signals

The server will respond to a number of signals:
SIGUSR1
Dump the internal (parsed) bootptab database to a file. The filename defaults to /tmp/bootpd.dump, but can be overridden using the commandline bootptabdumpfile argument.
SIGUSR2
Dump the current bindings and some packet statistics to a file. The filename defaults to /tmp/bind.dump, but can be overridden using the commandline -B option. Statistics include those dumped as a result of receiving the SIGWINCH signal described below.
SIGWINCH
Dump packet statistics to a file (not available on all systems). The filename defaults to /tmp/dhcpd.statistics, but can be overridden using the commandline -s option. Statistics include the number of each type of BootP and DHCP request and response packets the server has received or sent since it was started.
SIGHUP
Forces the server to re-read the dhcpd.conf and bootptab(5) files, even if they have not changed. This is not normally needed, since the server will re-read these files if they have been modified; it checks the modification times on these files every time it receives a request packet.
SIGTERM, SIGINT, SIGQUIT
Any of these causes the server to exit normally, first flushing to disk any lastbindings information that was still cached.
SIGABRT (SIGIOT)
This increases the debuglevel by one.
SIGSYS
This resets the debuglevel to 0 (not available on all systems).

Ip Address Selection

When a request packet arrives from a client, the server attempts to select an appropriate IP address for that client via a number of methods, trying each method in order until it finds an appropriate IP address or runs out of methods.

Selection of an "appropriate" IP address typically includes tests such as:

* ensuring that the address is appropriate given the network to which the client is presently attached

* for dynamically-assigned IP addresses, making sure the client is permitted to obtain an address on the relevant network, given the policy restrictions in the dhcpd.conf(5) file

* for statically-assigned IP addresses, making sure the Client Identifier matches that in the bootptab(5) file

* making sure that the IP address is not presently bound to a different Client Identifier

* the IP address is (still) in the bootptab(5) file

The methods are outlined below; they vary depending upon the type of request packet we receive:

Bootprequest

If the ciaddr field is 0, we look for any statically-assigned IP address associated with the client’s chaddr; if not found, and the htype = IEEE802, we also try bit-swapping chaddr and checking for a statically-assigned IP address again. Then we look for any current binding for the client’s chaddr that was assigned via BootP. Lastly, we look for a new dynamic IP address.

If the ciaddr field is non-zero, we look for this statically-assigned IP address.

Dhcpdiscover

We look for any statically-assigned IP address associated with the client’s Client Identifier. Then we look for any current binding for the client’s Client Identifier that was last assigned via DHCP. Next we look for the last binding assigned to the client’s Client Identifier, if any. Then if the Requested IP Address option was specified by the client, we look for that IP address. Finally, we look for a new dynamic IP address.

Dhcprequest

If the client is in the SELECTING state, we look for the IP address specified in the client’s Requested IP Address option among those in our current bindings (which include DHCPOFFERs) which were assigned via DHCP.

If the client is in the INIT-REBOOT state, we look for the IP address specified in the client’s Requested IP Address option.

If the client is in the RENEWING or REBINDING state, we look for the client in our current bindings assigned via DHCP. (Note that if the client is in the RENEWING state, we skip the test to determine if the IP address is appropriate for the network to which the client is presently attached. We also skip that test if the client is in the REBINDING state and is attached to a network to which the server is directly-attached; in both cases, giaddr is 0, and so cannot be tested.)

Redundant Servers

You may run dhcpd on more than one host on the same or different networks, to provide some level of redundant service in the event one server fails.

If you are using BootP Relay Agents, you will probably want to configure them to forward BootP/DHCP client broadcasts to all your redundant servers.

Redundant service also assumes that each server can receive and send packets to the same set of networks; if your network’s topology prevents some servers from communicating with some networks, redundancy will be reduced.

There are some limits on what kind of redundant service can be provided, because there is no communication between the servers; no server-to-server protocol is available at this time. What kind of redundancy service a client will receive varies, based on whether the client is using BootP or DHCP, and whether a static or dynamic IP address is being provided to the client.

BootP clients with Statically-Assigned Addresses

When providing statically-assigned IP addresses to BootP clients, each server provides full redundancy. The server maintains no "state" information about such assignments, and the client does not care which server responds.

Naturally, all the servers’ bootptab(5) files should reflect the same information; each server should associate the same clients and IP addresses.

DHCP clients with Statically-Assigned Addresses

If you are providing statically-assigned IP addresses to DHCP clients, each server provides some redundancy, as described below.

Naturally, all the server’s bootptab(5) files should reflect the same information; each server should associate the same clients and IP addresses.

When a client is in the INIT or INIT-REBOOT state, all servers will attempt to answer the client’s DHCPDISCOVER broadcasts; there is full redundancy.

When a client is in the SELECTING state, only the server that the client has selected can answer it; the other servers cannot provide redundant service.

When a client is in the RENEWING state, only the server to which the client is presently bound can answer it; the other servers cannot provide redundant service.

When a client is in the REBINDING state, only the server to which the client is presently bound can answer it; the other servers cannot provide redundant service. However, you can arrange for redundant service by enabling the Renew Unbound Statics feature; see the relevant section below for details.

BootP clients with Dynamically-Assigned Addresses

Because there is not yet a server-to-server protocol, the servers have no way to communicate amongst each other to learn what IP addresses each has assigned. Therefore, if you configure multiple servers to provide dynamic IP address assignment, you must provide each server with its own pool of such addresses; the IP addresses owned by each server may not overlap.

Assuming each server has available dynamic IP addresses for the same set of IP networks, then the servers will provide some redundancy, with several caveats:

When the client issues a BOOTPREQUEST, each server attempts to respond to the client. Each server assigns a (different) IP address from its own pool of available dynamic IP addresses for the client’s present network. Which BOOTPREPLY the client chooses to use is up to the client. As the BootP client has no way to inform the servers which IP address it has chosen, each server records its own assignment as a current binding, making the address unavailable for further assignment by this server. (BootP dynamic assignment are of infinite duration, although the server will discard one if it sees a request from the same client that makes it clear that the client is no longer bound to that IP address. You may also be able to use the Expire Infinite Dynamics feature (described in a section below) to eventually expire BootP-assigned dynamic addresses.)

Each server normally attempts to assign to the client the same dynamic IP address it was last assigned via BootP by this server (if the IP address is still available and appropriate for the client’s network, and no appropriate static IP address for this client is available). This is based on the principle that the client may be better served by keeping the same IP address it last had. However, in the presence of multiple servers, the client may choose a BOOTPREPLY from a different server than it did last time, causing it to use a different IP address than it used previously.

DHCP clients with Dynamically-Assigned Addresses

Because there is not yet a server-to-server protocol, the servers have not way to communicate amongst each other to learn what IP addresses each has assigned. Therefore, if you configure multiple servers to provide dynamic IP address assignment, you must provide each server with its own pool of such addresses; the IP addresses owned by each server may not overlap.

Assuming each server has available dynamic IP addresses for the same set of IP networks, then the servers will provide some redundancy, with several caveats:

When the client in the INIT or INIT-REBOOT state issues a DHCPDISCOVER, each server attempts to respond to the client. Each server assigns a (different) IP address from its own pool of available dynamic IP addresses for the client’s present network. Which DHCPOFFER the client chooses to use is up to the client.

Each server normally attempts to assign the client the same dynamic IP address it was last assigned via DHCP by this server (if it is still available and appropriate for the client’s network, and no appropriate static IP address for this client is available). This is based on the principle that the client may be better served by keeping the same address it last had. However, in the presence of multiple servers, the client may choose a DHCPOFFER from a different server than it did last time, causing it to use a different IP address than it used previously.

When a client is in the SELECTING state, only the server that the client has selected can answer it; the other servers cannot provide redundant service.

When a client is in the RENEWING state, only the server to which the client is presently bound can answer it; the other servers cannot provide redundant service.

When a client is in the REBINDING state, only the server to which the client is presently bound can answer it; the other servers cannot provide redundant service.

Renew Unbound Statics

Specifying the -u commandline option turns on the Renew Unbound Statics feature. This feature is useful if you plan to serve DHCP clients, and are assigning some (or all) IP addresses statically, and have multiple DHCP servers.

The DHCP specification says that when a client enters the RENEWING state, it unicasts a DHCPREQUEST to the server to which it is bound. If it receives no answer (including retries) after some period of time, the client enters a REBINDING state, and broadcasts the DHCPREQUEST. If it receives no answer (including retries) by the time the lease expires, it returns to the INIT state.

When the server receives a DHCPREQUEST from a client in the RENEWING (or REBINDING) state, it normally grants the renewal only if the client has an unexpired lease with this server. Otherwise the server ignores the request; the server to which the client is bound should answer the client. (The only exception is normally that if a server is sure the IP address the client is asking for is inappropriate for the client, the server will send a DHCPNAK, which forces the client back to the INIT state.)

If there were a DHCP server-to-server protocol in place today, multiple DHCP servers could exchange lease information. Then when a client went into the REBINDING state, any server that has received the lease information could respond to the client. But there is no DHCP server-to-server protocol at this time.

As a temporary measure, the Renew Unbound Statics feature may be used to cause your multiple dhcpd servers provide redundant service, if the IP address being requested is one that is statically-assigned to the client that’s asking. So if you have multiple DHCP servers all with the same set of static assignments in their bootptab(5) files, specifying the -u option when starting each of these servers will allow them to provide redundant service when clients go into the REBINDING state (e.g. because their original DHCP server is unavailable).

If the requested IP address is one that is dynamically-assigned, the Renew Unbound Statics feature has no effect. The server will not provide redundant service if it sees that the requested IP address is listed in the bootptab(5) as dynamically-assigned. (If the server sees that the requested IP address is dynamically-assigned, it behaves exactly as if the Renew Unbound Statics feature is not enabled. That’s because in the absence of a DHCP server-to-server protocol, we assume that you must configure each of your DHCP servers with independent ranges of dynamic IP addresses on each IP subnet for which they provide dynamic service.)

The Renew Unbound Statics feature has another use, even if you don’t have multiple servers. Imagine you have clients that have unexpired leases for statically-assigned IP addresses, but your server doesn’t know about their unexpired leases. (That would happen after you convert from another DHCP server product to this one, or you erase the bindings directory contents because it is corrupted.) Starting your server with -u will help deal with the problem. When the clients with leases try to renew them, the server will be able to answer them, even though the clients didn’t appear in the server’s list of unexpired leases. This trick provides a useful transition tool, or recovery mechanism from a last lastbindings directory, at least when static address assignments are involved.

Expire Infinite Dynamics

The Expire Infinite Dynamics feature allows the server to expire those assignments made to BootP clients for dynamically-assigned IP addresses.

BootP assignments are recorded by the server as infinite; BootP does not carry any duration information to the client, so the server must assume the client will keep the assignment forever. But if you have some external means to ensure that the BootP clients being assigned dynamic addresses will eventually timeout their assignments (e.g. power cycle clients periodically), then you may use the Expire Infinite Dynamics feature to tell the server reclaim those IP addresses after a period of time, making them available for re-assignment.

To turn on the Expire Infinite Dynamics feature, specify the expire_infinite_dynamics statement in the dhcpd.conf(5) file; it takes a required argument of a time (in seconds). The server will reclaim any infinite (i.e. BootP-assigned) dynamic IP address after that many seconds. (The reclaim actually happens during regular DHCP garbage collection.)

If you set expire_infinite_dynamics to 0, or simply leave it out of the dhcp.conf file (it is an optional statment), the Expire Infinite Dynamics feature is not enabled.

The server does not have an equivalent feature for infinite static IP address assignments, since this server does not actually record infinite (BootP-assigned) static assignments in the first place; those sorts of assignments are "stateless."

Multihomed Servers

This server was not designed to function on a multihomed host. This section describes the problems you will encounter if you must run this server on a multihomed host.

Short of redesigning the server to not rely on datagram sockets for reading and writing packets, the only reliably workaround to these problems is to not allow any clients to be attached to any of the IP networks to which the server is directly-attached.

Sending to the Broadcast Address

Sometimes the server needs to send a reply to the IP address 255.255.255.255. On a multihomed host, which interface this packet goes out is not well-defined. This is (deliberately) left unspecified in the current Host Requirements RFC.

Many operating systems send such packets out the host’s first-configured interface. In this case, if the client is attached to a different interface, then the packet won’t reach the client.

Some operating systems send such packets out all the host’s interfaces. If your host operates this way, this problem will not affect you.

(The one obvious workaround to the problem (short of reworking the server) will not solve the problem. The server could use a subnet-directed broadcast to force the reply packet out the appropriate interface (or all interfaces). While that would get the packet out the correct (or all) interfaces, then the the packet would contain a destination IP address other than 255.255.255.255. According to the BootP and DHCP specifications, these packets would not be recognized by the clients; valid BootP and DHCP responses sent to the broadcast address must use the broadcast address 255.255.255.255.)

If this problem affects you. then one kludgey workaround would be to have multiple servers, each with its primary interface on a different network. For example, if you must run dhcpd on a two-port server attached to networks A and B, with A being its primary interface, then run a second . dhcpd on another single-homed (or multi-homed) server which has a (primary) interface on network B. That way, the broadcasts to clients on network B that the first server cannot send will still be sent by the second server. Note that this assumes that both servers have identical configurations; any differences, including different dynamic IP addresses being served on network B, will prevent this workaround from correctly handling all cases.

Another workaround is to attach no clients to the networks attached to your multihomed server’s non-primary interfaces. That way, the server will need never send a broadcast to a client attached to a non-primary interface.

Interface for Incoming Packet Unknown

The DHCP specification says the server should, in most circumstances, check that the IP address it is about to hand to a client is appropriate for the network to which the client is attached. (There is one exception for clients in the RENEWING state, where the specification says the server should skip the appropriate-network check.)

This is not a problem for a single-homed server, but a multihomed server will sometimes have difficulty determine to what network the client is presently attached.

If the request packet was broadcast from a non-local network, the server may determine to what network the client is presently attached by inspecting the request packet’s giaddr field.

However, the giaddr field is not always set; if the client is attached to a local network (one to which the server is directly-attached), giaddr will be 0. (The giaddr field is 0 if the request packet was unicast by the client to the server, regardless of which network the client is attached to, but these are typically clients in the RENEWING state, and the server doesn’t have to perform the appropriate-network check, as per the specification.)

For DHCP requests that were broadcast, when the giaddr is 0, a single-homed server knows that the client must be attached to the same network as the server. But if the server is multihomed, the client could be attached to any of the networks to which the server is directly attached.

If the server could determine on what interface a request packet arrived, the server could deal with this. But this server listens to requests via a datagram socket, and is unable to determine on what interface a packet arrived.

Since the server doesn’t know on what interface the packet arrived, it checks the proposed IP address against all of the networks to which the server is attached; if the IP address is appropriate for any of those networks, the server proceeds on the basis that the IP address is OK for the client. (The server determines the list of server-attached networks by walking the OS’s interface list at server initialization, copying IP addresses and netmasks.)

As a result, the server may make incorrect decisions about whether an IP address is appropriate for clients attached to networks to which the server is directly attached.

As a workaround, you must will need to not allow the server to provide dynamically-assigned addresses on any of the networks to which the server is directly attached. Even this measure may not be sufficient if you have clients that move from one of these directly-attached networks to another; manually forcing the client to discard a current binding may be necessary after every move.

If you never attach clients to the networks that are directly attached to your multihomed server, this problem will not arise.

Check File Access

The Check File Access feature is enabled by default. You may disable it via the -A option. (You may also disable it via a compile-time option.)

If Check File Access is enabled, then whenever a BOOTPREQUEST arrives with a non-null file field, dhcpd will check to see if that file exists and is accessible on the server. (If file specifies a relative pathname, it is taken relative to dhcpd’s current working directory.) If the file does not exist, or is not accessible, dhcpd will not respond to the client.

Additionally, if Check File Access is enabled, then when a BOOTP OR DHCP packet arrives with a null file field, and a bootfile has been specified in the bootptab(5), dhcpd will check to see if that file exists and is accessible on the server. (If the bootfile specifies a relative pathname, it is taken relative to dhcpd’s current working directory.) If the file does not exist, or is not accessible, dhcpd will not include the bootfile in the response packet is sends to the client (if any).

If you store bootfiles on servers other than the one running dhcpd, (e.g. referring clients to them via the :sa: tag), then you should disable the Check File Access feature. (Leaving it enabled will cause the server to look for the bootfile locally, ignoring the client’s request when the file is not found.)

Running As an Unprivileged User

The server must be started as root. It needs to be able to perform several privileged operations at startup time. However, after it completes these operations, it only needs root privileges occasionally. (It needs root privileges whenever it needs to insert entries into the host’s IP ARP table to send a packet to a host on a directly-attached network.

To limit any accidental damage the server could do it it contains bugs, you can specify that the server should change its effective uid and/or effective gid to something other than root. After performing some startup operations, it will make the change.

To use this feature, specify the username (or uid) under which the server should run with the -U option; specify the groupname (or gid) under which the server should run with -G option. Note that this is only supported if the host supports seteuid().

While running, the server may need to manipulate the host’s IP ARP table from time to time. If it has changed its effective uid to something other than root’s, it will temporarily change its effective uid back to root’s to manipulate the IP ARP table.

Note that while this feature makes it less convenient to exploit the server’s root privileges if there are any bugs present in the server, it does not provide complete protection, since the server still retains a real uid of root.

To make best use of this feature, you should probably create a new user and group (assign (assigning a unique uid and gid); for the server to use; e.g. user dhcp and group dhcp.

The server needs to be able to read the bootptab(5) and dhcpd.conf(5) files, and needs to be able to read and write in the bindings directory. Set the owners/groups and/or permissions of the files and directories above to provide the necessary access to the user/group you selected for the dhcp server. Keep in mind that you don’t want to allow arbitrary users to modify the bootptab(5) and dhcpd.conf(5) files, or write in the bindings directory.

The server can write bootpd.dump and bind.dump files upon receipt of the appropriate signals. Make sure the user/group you selected for the dhcp server can write these files if you intend to send those signals to the server, and that the user that sends these signals has the necessary privilege to send those signals.

Allow ’server Ip Address’ Option in Renewal/Rebinding States

Specifying the -R commandline option turns on the Allow ’Server IP Address’ Option in RENEWAL/REBINDING States feature.

The DHCP specification says that DHCPREQUEST packets from clients in INIT-REBOOT, RENEWING or REBINDING states MUST NOT contain the Server IP Address option, while DHCPREQUEST packets from clients in the SELECTING state MUST contain the Server IP Address Option. Some DHCP clients (which reportedly include Windows 95) violate this by including a Server IP Address option in DHCPREQUEST packets when they are in the REBINDING state. That causes the server to believe the client is in the SELECTING state, and act accordingly.

If you enable the Allow ’Server IP Address’ Option in RENEWAL/REBINDING States feature, the server attempts to recognize these erroneous packets, and fix them by ignoring the Server IP Address option.

The erroneous DHCPREQUEST packets are characterized as those which meet the following criteria: they contain a (non-zero) Server IP Address option, AND they do not have a Requested IP Address option, AND they have a non-zero ciaddr header field, AND the server presently has a binding for the Client Identifier AND the binding for the Client Identifier is for the same IP address as the ciaddr.

Note that the first criteria above is the inappropriate option included by the broken client. The second and third criteria above are what would tell us that the client is in the RENEWING or REBINDING states, instead of INIT-REBOOT if the first inappropriate option were not present. The fourth and fifth criteria are an attempt to limit the incorrect decisions we could make in the event we receive an erroneous (by definition) packet which meets the other criteria. (Since once we treat the client as RENEWING/REBINDING, we may very well send a DHCPNAK; we want to avoid being too liberal in deciding packets belong in this category, especially as we may be only one of several DHCP servers.)

Note that a side effect of including the fourth and fifth criteria is that this feature will not be able to help a client which is bound to another DHCP server and is trying to rebind. As a result, this feature will only help the client who is bound to us and is trying to rebind (presumably because the client did not succeed in renewing with us earlier). (And as a result, enabling the Renew Unbound Statics feature will not help in this case.)

This feature has not been tested extensively, and (deliberately) causes the server to violate spec, so you should treat it as "experimental" and only enable it with caution.

Lone Dhcp Server

Specifying the -L commandline option enables the Lone DHCP Server feature. The feature causes the server to behave in ways that may be helpful, but would normally be unsafe in the presence of other DHCP servers.

RENEWING versus REBINDING

When we receive a DHCPREQUEST from a client, it is not always possible for us to distinguish the client state RENEWING from REBINDING. (This is because in some situations, we must see the IP destination address of the DHCPREQUEST packet to distinguish the two cases. The IP destination address is not available to an application using a datagram socket in many BSD-derived sockets implementations.)

This often does not create any difficulty, however, there are times we wish to respond to a client differently depending on whether the client is in the RENEWING or the REBINDING state. When a client asks us to renew a lease which we have not granted the client, we want to send a DHCPNAK. However, if the client is REBINDING, the client may have received the lease from another DHCP server, and in that case, we must be silent. That’s because we do not know definitively that the client may not be granted the requested lease, as another DHCP server may be able to grant the client’s request.

Our implementation normally follows the conservative approach in the situations above: it assumes the client may be REBINDING, so we are silent. The result is that REBINDING clients will work properly, but RENEWING clients that we’d like to NAK may be allowed to keep using their old leases (until the client believes the lease has expired, or the client reboots).

This is the only safe way we can run if there are other DHCP servers on the network.

If you enable the Lone DHCP Server Feature, instead of following the conservative approach above, we will assume the client is in the RENEWING state, so we will send a DHCPNAK.

Sending a DHCPNAK may force the client back to INIT state, allowing it to then proceed to obtain a valid DHCP lease. However, note that many clients will ignore the DHCPNAK, instead continuing to use the IP address they believe they have leased, until they believe the lease expires.

Dynamic Dns

This server does not presently support true Dynamic DNS. It is assumed that all IP addresses and associated hostnames in the bootptab are already registered in DNS; i.e. from the point-of-view of DNS, all the A records and PTR records associated with this DHCP server’s leases are static, regardless of whether the DHCP server is leasing addresses dynamically to DHCP clients.

However, this DHCP server presently includes an experimental feature associated with Dynamic DNS. In future versions of this DHCP server, the feature as described in this section may be removed or changed in incompatible ways.

RFC4702 The Dynamic Host Configuration Protocol (DHCP) Client Fully Qualified Domain Name (FQDN) Option specifies how DHCP clients and servers should use Dynamic DNS.

Some clients now attempt to perform Dynamic DNS by default. In the current version of this DHCP server, the DHCP client probably should not attempt to perform Dynamic DNS, because all the DNS A records and PTR records associated with IP addresses leased by the DHCP server should already be statically defined in DNS (static from DNS’ point of view, not necessarily from the DHCP server’s point of view).

According to RFC4702, if a DHCP client sends the Client FQDN option to the DHCP server, the corresponding response packet from the DHCP server should include the Client FQDN option (option 81), except in certain circumstances.

The option in the DHCP server’s response is supposed to communicate several pieces of information. As presently implemented by this DHCP server, when the server sends a Client FQDN option to the client, it will contains a flags value of 0x03, an rcode1 value of 0xFF, an rcode2 value of 0xFF, and a domain name value equal to the client’s fully-qualified hostname, in ASCII encoding.

This response (specifically, a flags value of 0x03) is supposed to tell the DHCP client that it should not attempt to use Dynamic DNS to update its A record. (Within the flags field, N=0, E=0, O=1, S=1). (There’s nothing defined in the specification to allow a DHCP server to actually tell the client that it should not try to update its PTR record; it is assumed the client will never do this.)

Unless configured otherwise, we follow the rules in RFC4702 that govern whether the Client FQDN option should be sent to the client. These rules are a bit different than the rules governing whether most other traditional options should be sent to clients. Unlike other options, the presence of Client FQDN option in a packet from the DHCP client triggers the inclusion of a Client FQDN option in the DHCP server’s response. (And as you’d expect, the option will also be included in the server’s response if it was present in the client’s Parameter Request List option, like many other options.) Note that this happens even though the client’s bootptab(5) entry may contain no cf tag. The value of the Client FQDN option is one that is computed by the server, not specified in the bootptab(5).

Associated with the feature is the new cf tag for the bootptab(5) file. It may only be specified with a value of 0x00 or 0x01; no other values are presently valid.

Specify a value of 0x00 to direct the server to never return a Client FQDN option to this client. Use this to suppress the experimental feature entirely.

Specify a value of 0x01 to direct the server to always return a Client FQDN option to this client, when the nr tag has also been set for this client, and the client is speaking DHCP. The server will also continue to return the Client FQDN option to clients that it normally would had the cf tag not been present in the bootptab entry at all. (Note that setting this tag to 0x01 for a client that does not have the nr tag set has no effect.)

We never return the Client FQDN option to BootP clients.

In this experimental implementation, we deviate from RFC4702 with regard to the encoding of the domain name. RFC4702 says that if a Client FQDN option specified by the DHCP client has the ’E’ flag bit set, the Client FQDN option the server sends to the client should also have the ’E’ flag set and should encode the domain name field using DNS-style encoding; if the client’s ’E’ flag bit was 0, the server’s ’E’ flag bit should be 0 and the server should encode the domain name in ASCII. However, our server ignores the value of the ’E’ flag sent by the DHCP client, and always encodes the domain name field in ASCII. We do not know if that causes any problems for any particular client implementations at this time.

In this experimental implementation, we are ignoring all the information contained in the Client FQDN option that the DHCP client might supply. We simply return a fixed response that means "here’s your FQDN, don’t try to update DNS."

In this experimental implementation, we also return the Client FQDN option if the client’s request contains a Parameter Request List option that mentions the Client FQDN option. This behavior is not specified in RFC4702.

Offer Terminates Unexpired Lease Feature

When the server has an unexpired DHCP lease for a client, and it receives a DHCPDISCOVER from that client, and it decide to OFFER the same IP address from the unexpired lease to the client, the server converts the unexpired lease to an OFFER. If the client SELECTs the offer before the offer expires, the offer becomes a new lease.

If the client does not select the offer before the offer expires (and nothing else happens to cause the offer to be discarded prior to its expiration), the server re-instates the old lease that had expired prior to the offer. That is, the offer does not terminate the old lease.

This behavior is relatively new, first appearing in version 3.3.7+PU-11. Prior to this, an unselected offer terminated the unexpired lease. If you prefer the old behavior, specify the -T option, which enables the "Offer Terminates Unexpired Lease" feature.

The default behavior (in which the "Offer Terminates Unexpired Lease" feature is disabled) helps reduce the impact of certain clients that obtain a lease, enter the INIT state before the lease expires, receive an DHCPOFFER, ignore the offer, and then resume using the old lease. (Apple Mac OS X 10.4.x began doing that. It became worse in Apple Mac OS X 10.5.x, in iPod OS, and in iPhone OS; each of those systems appears to maintain a cache of multiple unexpired leases, and may choose to resume using any of them.)

Note that this behavior only applies when the server decides to offer the client the same IP address as the one that appears in the unexpired lease. If the server decides to offer the client a different IP address, it still terminates the unexpired lease, because the server’s implementation can only store one binding per client at a time.

The default behavior helps prevent the DHCP server from handing the unexpired lease to another client (given that the first client may resume using that unexpired lease). It also means that the server may consume many more IP addresses that it does with the old "Offer Terminates Unexpired Lease" behavior, since the server doesn’t terminate leases as promptly as it otherwise could.

If you are using the default behavior and have multiple DHCP servers each with its own pool of dynamic IP addresses, you will find that many clients end up holding leases from more than one server at a time, wasting dynamic IP address pool space. This is because each time the client requests service, it may choose an IP address provided by a different server. Using the "Client Steering" feature may help reduce the waste, as it will tend to cause each client to prefer a particular server over the others.

Bindings Dump File

See the "SIGNALS" section to learn how to cause the server to write a file containing current bindings and some packet statistics.

Detailed documentation of the bindings file format is not yet available. This section contains selected information.

If a binding has the offerred_but_not_yet_accepted_by_client flag set to true, it represents an offer that has not yet been selected by a client. It could simultaneously represent an unexpired lease that was converted to an offer. To distinguish between those two cases, look for an expires_prior_to_offer_time_t or an expires_prior_to_offer. Bindings that are unselected offers that don’t also represent unexpired leases will lack both values; those bindings that have both values also represent unexpired leases.

Client Steering Feature

The Client Steering feature is a crude form of load balancing. You may use it when you have multiple servers, and wish each client to be steered so the client tends to prefer the servers in a particular order.

The Client Steering feature may be enabled with the client_steering_enable statement in the dhcpd.conf(5) file. The arguments to that statement are one or more of the following tokens: client_steering_enable_bootpreply_static, client_steering_enable_bootpreply_dynamic, client_steering_enable_dhcpoffer_static, and client_steering_enable_dhcpoffer_dynamic. Each token enables the Client Steering feature for just those response packets sent by the server. For example, client_steering_enable_dhcpoffer_dynamic specifies DHCPOFFER packets for dynamic IP addresses. Client Steering is not available for other kinds of response packets.

The Client Steering feature relies on the bootp_secs field in the header of every packet sent by a BOOTP or DHCP client. The client sets this value to the number of seconds that have elapsed since the client started trying to boot (but see below for exceptions).

The server computes a Client Steering Hashcode based on the request’s DHCP Client Identifier or bootp_chaddr. (This may be tuned via the client_steering_hash_source statement in the dhcpd.conf(5) file.)

The Client Steering Hashcode is used to determine whether this server is that client’s most preferred server, its second-most preferred server, its third-most preferred server, etc.

You must cause each server to take a different position in the sequence of servers; you specify this using the client_steering_server_myself statement in the dhcpd.conf(5) file. For example, if you had three servers, you would specify the value 1 on the one server, 2 on another server, and 3 on the remaining server. (You may specify the same value on more than one server if you want multiple servers to respond to the same clients using the same threshholds.)

If a client’s Client Steering Hashcode is 1, that client’s most-preferred server will be the server who’s client_steering_server_myself value is 1; that client’s second-most preferred server will be the server who’s client_steering_server_myself value is 2, and that client’s third-most preferred server will be the server who’s client_steering_server_myself value is 3. Similarly, If the client’s Client Steering Hashcode is 2, that client’s most-preferred server will be the server who’s client_steering_server_myself value is 2; that client’s second-most preferred server will be the server who’s client_steering_server_myself value is 3, and that client’s third-most preferred server will be the server who’s client_steering_server_myself value is 1.

The idea is that if you have n servers, each server will be the most preferred server for 1/n clients, the second-most preferred server for 1/n clients, etc. (This assumes the Client Steering Hashcode values are uniformly distributed.)

For any particular client, the most preferred server for that client responds to the client when the request’s bootp_secs is greater than or equal to some low value, typically 0 seconds. The second-most preferred server for that client also responds to the client when the request’s bootp_secs is greater than or equal to some slightly higher value, for example, 3 seconds. The third-most preferred server for that client also responds to the client when the request’s bootp_secs is greater than or equal to some slightly higher value, for example, 6 seconds, and so on.

You specify these threshholds using the client_steering_delay_secs statement in the dhcpd.conf(5) file. For example, if you had three servers, you might specify the values 0, 3, and 6.

If you specify n values for the client_steering_delay_secs, then presumably you have n servers, and will specify one of the values in the range 1...n for the client_steering_server_myself value on each server, specifing each value once. (It is permissible to specify the same client_steering_server_myself value on multiple servers, if you want multiple servers to respond to clients using the same threshholds.)

Ideally, a client will transmit its first request packet with bootp_secs set to 0. That client’s most preferred server will respond to the client. If the client doesn’t receive a response from that server, it retransmits its request packet with bootp_secs set slightly higher. Ideally, this slightly higher value will be large enough to cause both the client’s most preferred server and second-most preferred server to respond. If the client doesn’t receive a response, it retransmits its request packet with bootp_secs set slightly higher. Ideally, this higher value will be large enough to cause the client’s most preferred server, second-most preferred server, and third-most preferred server to respond, and so on. The result is that most of the time, the client would hear only a response from that client’s most preferred server, but the multiple servers would still provide a measure of redundancy for the client when the most preferred server is unavailable.

Note that the bootp_secs value specified by some clients is not accurate. RFC951 gives the client leeway in how it sets this field. And the pattern of timeouts and retransmissions used by different platforms may vary widely. As a result, it may be difficult to select a set of client_steering_delay_secs values that work well for a variety of clients. If a client always specifies a very low bootp_secs value, only one of the servers may respond to the client; the Client Steering will force that client rely entirely on a single server. Conversely, if a client always specifies a large bootp_secs value, all of the servers will respond to the client; that client will not be "steered" by the Client Steering feature.

The Client Steering feature may be of particular value when the Offer Terminates Unexpired Lease feature is not enabled. If you have multiple servers each with its own pool of dynamic IP addresses, you will find that over time a client may obtain a lease on a different dynamic IP address from each server. Although the client may need only a single lease, each of the servers will be maintaining a lease for the client. This wastes dynamic IP address pool space. Enabling the Client Steering feature for dynamic IP addresses may help reduce the waste, as it will tend to cause each client to choose leases from that client’s most preferred server, and less often from other servers.

Debug Levels

The server produces increasingly detailed output as the debuglevel increases from 0 to 16. If you’re not having any problems, but just want to understand the decisions the server is making, try running at debuglevel 7. Unless you have lots of free space or few clients, you normally won’t want to run with debuglevel higher than 2 or perhaps 3.

Here is a rough idea of what messages are added at each debuglevel:

  1. Server errors, operational problems, database corruption
  2. Major events affecting server’s operation (i.e. rereading databases). If compact messages have been enabled (via the -C commandline option), they appear at this level as well.
  3. Arrival of request packet, its IP source, length, the BootP or DHCP packet type, the Client Identifier or chaddr, and what IP address the server assigns/offers (only if the server decides to do so)
  4. Adds just a few messages indicating problems with the request packet (short packets, can’t decode options, etc.)
  5. Adds most of the detail about what state the client is in (as inferred by the server), and most of the steps the server makes to decide what IP address to assign/offer, or why it ignores or NAKs the client. (A few of the wordier or repetitious client-state messages are deferred to the next higher debuglevel.) Shows whenever a lease is expired or otherwise deleted. Also reports the host’s interface configuration at startup.
  6. Adds just a few messages: the wordier or repetitive messages about the state the client must be in, which would otherwise have appeared at the next lower debuglevel.)
  7. No additional messages
  8. Adds just a few messages indicating when the server is searching for an address to assign/offer, and appropriate-network checks. Also adds messages showing how the server determines the IP destination address for response packets
  9. No additional messages
  10. Adds some messages each time the dhcpd.conf(5) file is read.
  11. Shows the contents of some less-interesting fields in the request packet (e.g. bootfile, vendor magic cookie). When sending DHCPOFFER or DHCPACK, printers the lease expiration time, rebind time, and renew time. Reports BootP request packets that contain vend fields shorter than the legal minimum (these are still accepted). Reports request packets in which any Must-Be-Zero fields in the flags field are non-zero (these are still accepted).
  12. Shows when the server starts and finishes DHCP garbage collection, and when the server starts and finishes flushing cached lastbindings to disk
  13. When reading lastbindings from disk at startup, display the details in each record, and whether it was added to current bindings. During DHCP garabage collection display details about what’s done with each current binding. When re-reading dhcpd.conf or bootptab(5), display details about current bindings being removed.
  14. Shows the bootptab(5) file’s last modification time every time a packet is received. When sending packets, shows the maximum length of packet and number of bytes left.
  15. No additional messages
  16. No additional messages
  17. Adds all remaining low-level debug messages, typically involving maintenance of the data structures. To display these messages, the DEBUG compile-time option must also be defined.

Bugs

Individual bootptab(5) entries must not exceed 1024 characters nor 256 tokens.

Individual dhcpd.conf(5) statements must not exceed 1024 characters nor 256 tokens.

The contents of the lastbindings directory grows without bounds. One record is maintained for every Client Identifier ever seen by the server, containing the last binding assigned to that client. (The number of files in this directory will not grow beyond 256 (each represents one bucket in a hash table).) This is not a serious problem unless you have very high turnover in the clients you serve; at a site with 16,000 clients of which 13% are replaced over the course of a year, the bindings directory was under 512K after one year. If necessary, you can stop the server and erase all the files in the bindings directory, then restart the server; this has the side-effect of discarding all current leases.

The server is single-threaded, handling just one request packet at a time. A single broken client that floods the server with requests can act to deny service to other clients.

There may be a slow memory leak.

Running this server on a multihomed host is problematic; see the MULTIHOMED HOSTS section above.

Information about current bindings and lastbindings is stored using the Client Identifier as the key. The current DHCP specification says that the key should be the Client Identifier concatenated with the IP subnet that associated with the bound IP address. This means that when a client moves back and forth among several subnets, we won’t try to assign it the same address it had the last time it was on that subnet, since we only record one last binding per client, not one per subnet.

There are times that the server should respond to a DHCPREQUEST with a DHCPNAK, but instead is silent. This is typically because the server is supposed to be silent if the client is in the REBINDING state, but send a DHCPNAK if the client is in the RENEWING state. If the giaddr field is 0, the server must examine the request packet’s destination IP address to determine in which state the client is. (If the packet’s IP destination is 255.255.255.255 the client must be in the REBINDING state, otherwise the client is in the RENEWING state.) However, the request packet’s IP destination field is not available to the server as reading from a datagram socket. When confronted with this problem, the server will take the conservative approach, and be silent. As a result, some clients that would have otherwise received a DHCPNAK (and quickly moved back to the INIT state) will instead waste time in the RENEWING and REBINDING states.

When a DHCP client successfully renews a lease, much of the information the server provides in the DHCPACK is copied from the current lease. This is a problem if any of those values have changed in the bootptab(5). (E.g. you modify the bootptab(5) to change the lease time, IP gateway list, subnet mask, etc.) To get the new values to the client, the existing lease must go away -- e.g. by expiring, the client releasing it, or the server deciding to remove it with extreme prejudice. Note that major changes that invalidate the client’s lease (e.g. removal of the IP address from the bootptab(5), or if you are restricting service to registered clients, removal of the clientid from the bootptab(5)) cause the server to remove the unexpired lease, so that’s one ugly workaround.

The DHCP specification says that when offering an IP address to a client, the server should first try to offer an IP address associated with a current binding (or oldbinding) for this client (assuming the IP address is still appropriate for the client). Instead, this server will first try to offer an IP address that is statically-assigned to this client in the bootptab(5) (assuming the static IP address is appropriate for the client); if no such static IP address is available or appropriate, then the server proceeds to look for a current binding or old binding. The DHCP specification’s intent is presumably to try to let a client keep using the same IP address for as long as possible. The reason this server behaves differently is so that if a mobile client moves from its home network to another one where it obtains a dynamic address, if the server administrator later assigns this client a static IP address on its new network, it may eventually switch from its old dynamic address to its new static one. (The client will keep using the dynamic address as long as it keeps renewing an existing lease on that address, or reboots in the INIT-REBOOT state and requests the dynamic address when that address is available.)

Although the DHCP specification does not specifically prohibit a Client Identifier option value of all-zeros, this server will deliberately not respond to such messages. While legal, they almost certainly indicate a client that is misconfigured or broken.

If you use the -I option, the resulting behavior violates the DHCP specification, which does not indicate the server may ignore a Client Identifier specified by the client. (This is an intentional "bug.")

If you use the ’de’ tag in a bootptab(5) entry, the resulting behavior violates the DHCP specification, since we may send a DHCPNAK under circumstances not outlined by the specification. (This is an intentional "bug.") PP If you specify the -R option to enable the Allow ’Server IP Address’ Option in RENEWAL/REBINDING States feature the resulting behavior violates the DHCP specification. (This is an intentional "bug.")

The server does not support infinity (0xFFFFFFFF) as a valid value for lease times in the bootptab(5).

dhcpd only records information about the server’s interfaces when it starts up. If an interfaces is DOWNed (or UPped) while dhcpd is running, or the IP address, subnet mask, network number, or broadcast address associated with an interface is changed, you must kill and restart dhcpd for it to recognize this. If you remove one of the server’s IP addresses, some DHCP clients with current bindings may fail to renew their leases if they were using the Server Identifier corresponding to the server IP address you removed.

When constructing a DHCPOFFER or DHCPACK, the server only returns a subset of all those options present in the bootptab entry: those that it always attempts to supply (the IP address, bootfile (if specified), TFTP server address (if specified), lease time, renewal time, rebinding time, and user class (if specified), plus those explicitly requested by the client in its Parameter Request list option (if any). (The spec says the server should return any options whose value differs from the defaults specified in relevant RFCs.) You can use the nr bootptab tag to force the server to return all the bootptab options to the client in DHCPOFFER and DHCPACK packets.

If the server finds it must overload the file or sname fields (DHCP Option Overload), any values that were already in those fields are overwritten, instead of moved to the new options designed to hold them.

If you use specify any bootptab(5) option using a generic (Txxx) tag, that option will only be returned to DHCP clients if you also specify the nr tag. This is true even if the client specifically requests the option in an Parameter Request List option.

When sending a reply to a DHCP client, any bytes in the options field following the END option are supposed to be filled with PAD options. We don’t do this yet.

We do not respond to DHCPINFORM packets at this time; they are recognized and ignored.

We ignore any suggested DHCP Lease Time in the client’s DHCPDISCOVER or DHCPINFORM packets. Since the "Maximum Lease Time" (ml) tag is intended to be used to bound our response to these suggestions, presently we don’t use any ml value you specify.

We do not yet implement RFC2241 (DHCP Options for Novell Directory Services) and RFC2242 (NetWare/IP Domain Name and Information).

If the server leases an IP address to client, then before the lease expires, the bootptab(5) and/or dhcpd.conf(5) files are changed to cause that binding to become invalid, the server will discard the binding when it re-reads the files (at server re-start or upon receipt of a packet). However, the client may still be using the IP address until the lease expires; this can be a particular problem if the IP address is a member of a dynamic pool, or has been statically re-allocated to another client.

We do not yet implement RFC3396 (Encoding Long Options in the DHCP).

Credits

This dhcpd server traces its lineage back to earlier bootpd servers.

The original BOOTP server was created by Bill Croft at Stanford University in January 1986.

Carnegie Mellon University’s bootpd was primarily the work of David Kovar, Drew D. Perkins, and Walter L. Wimer, at Carnegie Mellon University. It was derived from Bill Croft’s earlier server, and merged most of the enhancements and bug-fixes from the NetBSD, Columbia, and other versions.

Enhancements and bug-fixes to bootpd were contributed by: Danny Backx <db at sunbim dot be>, John Brezak <brezak at ch dot hp dot com>, Frank da Cruz <fdc at cc dot columbia dot edu>, David R. Linn <drl at vuse dot vanderbilt dot edu>, Jim McKim <mckim at lerc dot nasa dot gov>, Gordon W. Ross <gwr at mc dot com>, Chris Tengi <tengi at CS dot Princeton dot EDU>, and Jason Zions <jazz at hal dot com>.

The CMU version of dhcpd was the work of Christopher Davis <chr+ at andrew dot cmu dot edu> of Carnegie Mellon University, and was based on the earlier bootpd server. The SNMP code is derived from the modifications made on the SNMP agent for mrouted3.8 by Dave Thaler.

The Princeton patches to CMU dhcpd are primarily the work of Irwin Tillman <irwin at princeton dot edu>, with contributions by others listed below.

Enhancements and bug-fixes to dhcpd were contributed by: Marc Beuchat <marcb at sianax dot neu dot sgi dot com>, Mohamed Ellozy <ellozy at netman-mel dot dfci dot harvard dot edu), Howard Harvey (howard <dot> harvey <at> myrealbox <dot> com), Bruce Hudson <hudson at Snoopy dot UCIS dot Dal dot Ca>, Brandon Hume, Petr Lampa <lampa at fee dot vutbr dot cz>, Robert Lee <robert at spin dot net dot uky dot edu>, Mel Lew <melvin at columbia dot edu>, Jeff Licquia <jal at cssroute dot lexdoc dot com>, Donald Matthews <DMatthews at globeandmail dot ca> David M. Meyer <meyer at network-services dot uoregon dot edu>, Jay Plett <jay at silence dot princetond to nj dot us>, Tim Rice <tim at trr dot metro dot NET>, Andreas Steinmetzler <astein at pallas dot de>, Chris Tengi <tengi at CS dot Princeton dot EDU>, Stephen C. Trier <trier at odin dot ins dot cwru dot edu>, and Nancy L Wong <nancy at watsun dot cc dot columbia dot edu>.

This list is probably incomplete.

Files

/etc/bootptab
Database of clients (and dynamic IP addresses) read by server. See bootptab(5). The name of this file can be overriden by a commandline argument or a compile-time option.
/etc/dhcpd.conf
Configuration file read by server, containing some tuning parameters, information about the server’s interfaces, BootP Relay agents on the network, and any pools of dynamically-assigned IP addresses. See dhcpd.conf(5). The name of this file can be overriden by a commandline argument or a compile-time option.
/etc/dhcpd.pid
Contains the processid of the server; written by server when it is running standlone (not started from inetd). The name of this file can be overriden by a commandline option or a compile-time option.
/tmp/bootpd.dump
Dump of parsed bootptab created by server when it receives a SIGUSR1 signal. The name of this file can be overriden by a commandline argument or a compile-time option.
/tmp/bind.dump
Dump of current bindings and packet statistics created by server when it receives a SIGUSR2 signal. The name of this file can be overriden by a commandline option or a compile-time option.
/etc/services
Internet service numbers, if NIS is not running.

See Also

bootptab(5), dhcpd.conf(5), dhcp-bindings-tool(8)

Internet Request For Comments:

RFC951
Bootstrap Protocol
RFC1534
Interoption Between DHCP and BootP
RFC1542
Clarifications and Extensions for the Bootstrap Protocol
RFC1700
Assigned Numbers
RFC2131
Dynamic Host Configuration Protocol
RFC2132
DHCP Options and BootP Vendor Extensions
RFC2241
DHCP Options for Novell Directory Services
RFC2242
NetWare/IP Domain Name and Information
RFC2485
DHCP Option for The Open Group’s User Authentication Protocol
RFC2610
DHCP Options for Service Location Protocol
RFC2937
The Name Service Search Option for DHCP
RFC2939
Procedure and IANA Guidelines for Definition of New DHCP Options and Message Types
RFC3004
The User Class Option for DHCP
RFC3011
The IPv4 Subnet Selection Option for DHCP
RFC3046
DHCP Relay Agent Information Option
RFC4702
The Dynamic Host Configuration Protocol (DHCP) Client Fully Qualified Domain Name (FQDN) Option
RFC3942
Reclassifying DHCPv4 Options

Internet Engineering Task Force draft documents are listed at the official IETF DHCP Working Group page: http://www.ietf.org/html.charters/dhc-charter.html

Additional DHCP resources are at: http://www.dhcp.org/

There are no known Y2K problems with the code.


Table of Contents