README for Princeton Patch 10 October 24 2008 irwin at princeton dot edu This file accompanies Princeton Patch 10 to CMU-dhcpd 3.3.7; it describes how to apply the patch, and what has changed. After you have applied the patch, you no longer need this file, since the information in it also appears in the RELEASE_NOTES file which results from applying the patch. This patch (as well as the complete pre-patched current distribution) is available via: http://www.net.princeton.edu/software/dhcpd/ ========================================================================= UPDATING FROM PATCHLEVEL 9 The patch is against dhcpd version 3.3.7 as distributed by CMU, with Princeton patches 1, 2, 3, 4, 5, 6, 7, 8, and 9 already applied. Assuming you have already applied the previous patches, you can apply this patch as follows: 0. Since this patch introduces new behavior as well as bug fixes, review the "WHAT'S CHANGED" section below before proceeding. 1. Make a record of any local customizations you have made to the product, such as changes you have made to 'Makefile' (or possibly 'Makefile.in') and 'defaults.h'. If you did customize either 'Makefile.in' or 'defaults.h' files, put the original version back to ensure the patch will apply cleanly. 2. Change to the directory containing the dhcpd source, and feed the patch file to the 'patch' program. (The 'patch' program is not supplied here; it is included with many operating systems, and is freely available from many software libraries.) E.g. using GNU patch: patch -p0 < CMU-dhcpd-3.3.7-PU-patch10 3. Please check for, and remove, any of the following obsolete files you find ('patch' may have removed them for you): ./configure.in ./install.sh 4. Fix permissions that 'patch' was unable to do: chmod +x tools/dhcp-bindings-tool 5. Run 'make distclean' to remove old object files, Makefiles and configuration info. 6. If you had previously customized any 'Makefile.in' files (as opposed to customizing any 'Makefile' files) , now's the time to re-apply your customizations if necessary. (You *did* make a record of them, right?) Most of the definitions that used to be in Makefile.in have moved to defaults.h, so you may not need to make any changes to any 'Makefile.in' files at this time. Before re-apply any of your old customizations, first check to see if you can now accomplish what you need with a commandline option instead of a compile-time definition; most defaults and features that once required a compile-time definition can now be overridden using commandline options. Commandline options are covered in the in the dhcpd.8 man page. If you do change any 'Makefile.in' files, save the originals first, so you'll have clean copies available when it comes time to apply the next patch. 7. Run './configure' to figure out your system's configuration and generate new 'Makefile' files from the 'Makefile.in' files. 8. If you had previously customized any 'Makefile' files (as opposed to any 'Makefile.in' files), now's the time to re-apply your customizations. if necessary. (You *did* make a record of them, right?) Most of the definitions that used to be in 'Makefile' files have moved to defaults.h, so you may not need to make any changes to 'Makefile' files at this time. Before re-apply any of your old customizations, first check to see if you can now accomplish what you need with a commandline option instead of a compile-time definition; most defaults and features that once required a compile-time definition can now be overridden using commandline options. Commandline options are covered in the dhcpd.8 man page. 9. Examine the 'defaults.h' file and customize it if necessary. This file now contains many of the definitions that previously lived in Makefile.in. Avoid changing items that can also be set using a commandline option. If you do change the 'defaults.h file, save the original first, so you'll have a clean copy available when it comes time to apply the next patch. 10. Run 'make' to compile the program. If you receive any compile-time errors, review the INSTALL document for tips. 11. Kill any running dhcpd, then install the new dhcpd executable. (It often lives in /etc/dhcpd or /usr/local/etc/dhcpd, but you may install it elsewhere.) You'll probably want to back up your old dhcpd executable before installing the new one. 12. Optionally install the new dhcpd.8, bootptab.5, dhcpd.conf.5, and dhcp-bindings-tool.8 man pages manually. 13. Optionally update any startup script you may use to take advantage of new commandline options added in this patch. 14. Optionally update your bootptab file to take advantage of new tags added in this patch. 15. Optionally update your dhcpd.conf file to take advantage of new configuration features added in this patch. 16. Start the new dhcpd executable. --------------------------------------------------------------------- BUILDING FROM SCRATCH You can get the current version of the source from http://www.net.princeton.edu/software/dhcpd/ Then see the INSTALL document for instructions. --------------------------------------------------------------------- PLATFORMS This code is currently in production at Princeton, but has NOT been tested extensively in all environments. In particular, I'm presently compiling and running on: Solaris 9 SPARC, with gcc 4.1.2 Solaris 10 SPARC, with gcc 4.2.4 --------------------------------------------------------------------- WHAT'S CHANGED Changes since PU patch 9: --- You may dump the packet statistics to a file by sending a SIGWINCH to dhcpd. (This signal is not available on all platforms.) These are the same packet statistics included at the start of a bindings dump, but performing just a statistics dump doesn't involve the overhead of performing a complete bindings dump. The statistics dumped with SIGWINCH are also surrounded with a start and stop delimiter line containing the time_t value, which may be helpful if you are parsing this data. The statistics file defaults to /tmp/dhcpd.statistics, and may be overridden with the new commandline argument -s. (The bindings dump output has not changed.) --- Added new dhcpd.conf optional statements: delay_reply_dhcpoffer, delay_reply_dhcpack, delay_reply_dhcpnak, delay_reply_bootpreply, and delay_reply_default. Here is the new information from the dhcpd.conf man page: These statements are optional, and may be used to cause the server to add a delay before sending BOOTPREPLY, DHCPOFFER, DHCPACK, and DHCPNAK packets. Specify: delay_reply_dhcpoffer n delay_reply_dhcpack n delay_reply_dhcpnak n delay_reply_bootpreply n delay_reply_default n where n is an integer (n < 2^32-1) specifying the number of microseconds (millionths of a second) to delay. The delay_reply_default value is used when a no value specific to the flavor of packet has been specified. All values default to 0. --- When we re-read the bootptab file because it has changed, we previously invalidated a current DHCP lease in the following situations: * the leased IP address is no longer in bootptab * the leased IP address was static, and the IP address in bootptab now has a different hardware address or Client Identifier associated with it We have added the following two cases that will also invalidate the current DHCP lease: * the leased IP address was static, and the hardware type (htype) for the lease does not match the hardware type for the IP address in bootptab * the leased IP address was static, but the hostname for the lease does not match the hostname for the IP address in bootptab --- If we receive a DHCPRELEASE message for a "lease" that represents an offer we made which the client never accepted, ignore the DHCPRELEASE. This is to work around a bug introduced by Microsoft in multiple versions of Windows shortly before August 2003. The bug is that sometimes the DHCP client sends a DHCPDISCOVER, receives DHCPOFFER(s), then sends a DHCPRELEASE for its previous DHCP lease, then sends a DHCPREQUEST for (one of) the offered lease(s). If the IP address that was part of the previous lease is the same one as the one that was offerered and then requested, we have a problem. Our server implements an offer as a very short lease (not as some unique structure different than a lease). As a result, the DHCPRELEASE causes the offer to be discarded. When the DHCPREQUEST arrives, we no longer have an outstanding offer for this client. This is a client bug; when it sent the DHCPDISCOVER, it must have moved to the INIT state. As a result, it no longer is BOUND, so is not entitled to send a DHCPRELEASE. Furthermore, at the time it sends the DHCPRELEASE it is in the SELECTING state (it has received the DHCPOFFER and has not yet sent the DHCPREQUEST); DHCPRELEASE is not a message a client may sent in the SELECTING state. We refer to this as the "Microsoft Windows DHCP RELEASE while SELECTING bug." We reported the bug to Microsoft. They agreed that this behavior is a new one in Windows, added to implement a new feature. However, they do not agree that it is a bug; their response is that a single DHCP client instance (i.e. one operating on a single interface with a single Client Identifier) is permitted to be both in the BOUND and SELECTING state simultaneously. (This implies that one such instance may have two simultaneous DHCP leases.) Since the client BOUND, it may send a DHCPRELEASE, and since the client is also SELECTING, it may send a DHCPREQUEST. I tried to convince them that this is not permitted by RFC 1541, but their response was that since the RFC did not forbid a client from being in two states at once, it is permitted. This seems incorrect to me; a finite state automata can be in only one state at a time. Nevertheless, Microsoft said that their behavior is correct; they will not change it. As a workaround, when we send a DHCPOFFER, we mark the coresponding "lease" in memory to reflect that it represents an offer that the client has not yet accepted. If the client later sends a DHCPREQUEST for this offer, we clear that mark. This mark allows us to determine if a lease structure in memory is a true lease, or simply an unclaimed offer. When we receive a DHCPRELEASE, if the lease referred to is one marked in this way, we ignore the DHCPRELEASE. From our point of view, the client is trying to release something isn't a true lease. As far as we're concerned, the client is in SELECTING state, so cannot release. --- Added new '-E so_rcvbuf' option to let you override the operating system's default size for the socket receive buffer. --- Added new '-F' option to let you enable the new "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. --- Added new 'readtabinterval' optional keyword to dhcpd.conf. The readtabinterval statement is optional, and may be used to reduce the frequency at which dhcpd(8) checks the bootptab(5) file for changes. If readtabinterval is unspecified (or specified as 0), then before processing each received packet, the server checks the bootptab(5) file's modification time. If the file's modification time is newer than the file's modification time at the time the file was last read, the server re-reads the bootptab(5) file. If a positive value is specified, then before processing each received packet, the server checks whether the speci- fied number of seconds have passed since the bootptab(5) file was last read. If fewer seconds have passed, the server does not check file's modification time; the file is not re-read. If the specified number of seconds have passed, the server proceeds to examine the bootptab(5) file's modification time (as described earlier). This feature allows you to reduce the frequency of the (relatively) expensive retrieval of the bootptab(5) file's modification time. The bootptab(5) is still re-read when the server is signalled to do so, regardless of the use of readtabinterval. --- Added new 'readconfinterval' optional keyword to dhcpd.conf. The readconfinterval statement is optional, and may be used to reduce the frequency at which dhcpd(8) checks the dhcpd.conf(5) file for changes. If readconfinterval unspecified (or specified as 0), then before processing each received packet, the server checks the dhcpd.conf(5) file's modification time. If the file's modification time is newer than the file's modification time at the time the file was last read, the server re-reads the dhcpd.conf(5) file. If a positive value is specified, then before processing each received packet, the server checks whether the speci- fied number of seconds have passed since the dhcpd.conf(5) file was last read. If fewer seconds have passed, the server does not check file's modification time; the file is not re-read. If the specified number of seconds have passed, the server proceeds to examine the dhcpd.conf(5) file's modification time (as described earlier). This feature allows you to reduce the frequency of the (relatively) expensive retrieval of the dhcpd.conf(5) file's modification time. The dhcpd.conf(5) is still re-read when the server is signalled to do so, regardless of the use of readconfinterval. It is also re-read whenever the server re-reads the bootptab(5) file. --- The format of a message produced when a DHCP packet's hlen field does not correspond with its htype field has changed. The old message looked like this: bad addr len from DHCP client with Ethernet address 00:01:D0:AF:B0:02 (IPsrc=192.168.1.3) The new message looks like this: bad addr len (BOOTP htype=1, but hlen=28) from DHCP client with Ethernet address 00:01:D0:AF:B0:02 (IPsrc=192.168.1.3) --- Added a new tool 'dhcp-bindings-tool' which may be used to manipulate the bindings directory. From the dhcp-bindings-tool(8) man page: dhcp-bindings-tool may be used to read a bindings directory in the format used by Carnegie Mellon University dhcpd with the Princeton University patches, henceforth referred to as CMU+PU dhcpd, or simply dhcpd. After reading the bindings into memory, the program may op- tionally prune the in-memory data. After any optional prun- ing, the resulting in-memory data may be written to create a new bindings directory, written to a plain text report file, and/or used as the basis to write a plain text statistics file. The program can also read the plain text report file instead of a bindings directory. This allows you to use the program to write a report based on a bindings directory, manipulate that report using other software, then read the resulting report to create a new bindings directory. The program relies on perl 5.8.0 or later, and the following modules from the Comprehensive Perl Archive Network (CPAN): Readonly, Statistics::Descriptive. From the INSTALL file: Optionally copy tools/dhcp-bindings-tool to wherever is appropriate on your system for local utilities (e.g. perhaps /usr/local/bin). This tool is not necessary to use dhcpd; it is a utility to allow you to manipulate the bindings directory created by dhcpd. The tool requires perl version 5.8.0 or later. If your perl is not in /usr/local/bin, you may need to edit the tool's first line to specify your perl location. The tool requires CPAN modules Readonly and Statistics::Descriptive. --- Added two alternate hash functions, neither of which is used by default. In INSTALL and defaults.h, recommended that you increase HASHTABLESIZE to a much larger number than the default (257), and uncomment ALT_HASHFN_2. These changes are best done at initial installation. While either (or both) may be done later, if you do either (or bother) you will need to stop the server and erase the entire contents of the bindings directory. Discarding all bindings is disruptive to clients. --- Fix AC_UNP_CHECK_TYPE in aclocal.m4 so it works in gcc 4.1.2. The bug would cause configure to believe that the system lacked a definition for socklen_t, causing us to provide our our definition, which could lead to duplicate or conflicting definitions. --- Remove declaration of interface_tab[] from bootpd.h. This was dead code, and also caused a compile-time error in gcc 4.1.2. --- #include if present. This will eliminate some warnings (e.g. for bcopy(), bcmp(), and bzero()) on some systems. --- Upgraded from autoconf 2.13 to 2.63. Renamed configure.in to configure.ac. Deleted acconfig.h. Replaced install-sh with install.sh version 2008-01-08 from automake 1.10.1. Replaced config.guess with config.guess version 2008-01-16 new version from automake 1.10.1. Replaced config.sub with config.sub version 2006-12-25.00 from automake 1.10.1. Add missing version 2006-05-10.23 from automake 1.10.1. ---