README for Princeton mods version 3 December 26, 1996 irwin@princeton.edu This file contains information about version 3 of the Princeton mods to CMU-dhcpd 3.3.7. The patch is available via: http://www.princeton.edu/~irwin/dhcpd.html --------------------------------------------------------------------- APPLYING THE PATCH The patch is against dhcpd version 3.3.7 as distributed by CMU, with Princeton patches 1 and 2 already applied. So if you are starting from scratch, first get dhcpd 3.3.7 from CMU, then apply Princeton patches 1, 2 and 3 in order; each of the Princeton patches via available at the URL above. You may have some local patches you'll need to reconcile against this. --------------------------------------------------------------------- PLATFORMS This code is currently in production at Princeton, but has NOT been tested extensively in all environments. In particular, I've only compiled and tested on SunOS 4.1.4 and Solaris 2.5.1. --------------------------------------------------------------------- WHAT'S CHANGED Here are the changes since Princeton patch 2: --- We could crash in free_client_info() in dhcp.c, due to freeing a variable that wasn't malloc'd. (Reported by several people.) Thanks to Andreas Steinmetzler , Marc Beuchat , and others, for pointing this out. --- There was a bug in dhcp_request() in dhcp.c. A client would boot and be assigned a dynamic IP address. The client restarted before the lease expired, and came up in INIT-REBOOT state. The server still had the current binding, as it should. The client specified the same IP address it had before in the Requested IP Address option. The server would incorrectly report that current binding was assigned via BootP instead of DHCP, and clear it, then assign a fresh one. (The new assignment could be the same just-freed dynamic IP address, or another dynamic one.) Now the server properly recognizes that current binding was assigned via DHCP and re-uses it. --- Jeff Ross reported the following error appearing repeatedly in syslog: "Tried to assign an ip which already had a binding (ip address here)". I found three likely causes for the problem: 1) When we got a DHCPDISCOVER and do not find a current appropriate binding for this client to re-use, we next checked the client's lastbinding to see if that is appropriate, and if so, re-use it. However, we were failing to check if that IP address was already bound to someone else; now we check that, and if so, do not use that address. If the lastbinding was not present or not appropriate, and the client specified a Requested IP Address option, we check to see if it is appropriate, and if so, use it. However, we were failing to check if that IP address was already bound to someone else; now we check that, and if so, do not use that address. (Changed dhcp_discover() in dhcp.c) 2) The problem could also be caused by the following bug: When we got a DHCPREQUEST from a client that is INIT-REBOOT, and the Requested IP Address is a dynamic IP address, and that address is appropriate for the client, and is not presently bound, we grant it to the client. We were putting it into the ipboundhshtbl, but failing to remove it from the pool of available dynmamic IP addresses. (Changed dhcp_request() in dhcp.c) 3) The problem could also be caused by misconfiguration: If the dhcpd.conf file contains 'network' statements in which the IP addresses ranges overlap, bad things can happen, including this. Added code to get_dynamic_ip() in dynamic.c to provide more diagnostics. Added warning about overlapping 'network' statement IP ranges to the dhcpd.conf sample file. (Though we are not specifically checking for this configuration error; we won't warn in all cases, just those we notice.) --- Jeff Ross and Andrew Smith Andrew Smith saw "hash_Insert(boundhshtbl) failed! Something's wrong!", "not increasing 'leases' counter...so count may no longer be right" messages. I think most of these were cured with the fixes above, but not all. The remaining causes may be associated with the boundhshtbl and ipboundhshtbl falling out of sync. (Both reflect the current bindings; the first is keyed by clientid and the second by ip address.) It's possible that this is triggerred by having multiple clients attempting to use the same clientid. I've added some more text to the error messages, to make it clearer what state we're in when they happen. I've located a couple places where we were letting the two tables fall out of sync, and fixed them. As we always assumed these two tables were in sync, we typically only looked things up in one of the two tables (whichever was more convenient given the data we had). Now we look things up in both tables, and check that everything agrees. If we find that things don't agree, we'll produce more error messages, which may help track down any remaining bugs in this area. Although I've added all those tests, I've not been able to exercise all the paths through the code, as I've not been able to produce most of the pathological condictions they're intended to catch. --- Jay Plett found that dhcp_inform() was not putting the user class value into the reply packet correctly, since it was mistakenly looking at the length of the vendor identifier value. Included his fix. --- Included UnixWare patches from Tim Rice : The INSTALL macro in the top-level Makefile.in is now @INSTALL@ instead of 'install'. (Also from ChrisTengi .) The CC macro in all Makefile.in files is now @CC@ instead of gcc. (Also from Chris Tengi .) The top-level Makefile has a new 'distclean' target you can use to remove all the files built by 'configure'. Added support for socket APIs with "buffer length" size other than int. There's a new CONFIG_SOCKARGLENTYPE def which 'configure' will set to trigger the use of the new socklen_t typedef. configure now tests for and defines SVR4. configure now tests for libgen and sets LIBS appropriately. configure checks for stropts.h and defines a new HAVE_STROPTS_H accordingly. configure now checks for UnixWare, and if found, adds -lresolv to LIBS (needed for strcasecmp), and defines the new XDEFS to be -D_KMEMUSER. The Makefile.in files for dhcpcmd and snmpd now includes XDEFS when setting DEFS, to get the -D_KMEMUSER. Added include of net/if.h to a couple places, include of fcntl.h, stropts.h based on new HAVE_STROPTS_H. The initialtion of servers[] in dhcpcmd.c is now ' { NULL }' instead of '{ }'. (You still need to replace this with your servers if you want to actually use dhcpcmd.) Fixed some variable types and added some casts to eliminate compiler warnings. Added some new-style function prototypes. --- Included Chris Tengi's corrections to man/bootptab.5 to include various missing tags. --- Included Chris Tengi's patch to process_bindata() in readfile.c; 'str' was not being initialized. --- If we have trouble parsing dhcp options, attempt to report the client identifier or chaddr, if possible. --- Updated bootptab(5) man page to describe how the $V, $C, and $DHCP override entries work. Updated references to RFCs and Internet Drafts. Updated to refer to dhcpd, not bootpd. Moved some sections around. --- Some broken or misconfigured clients apparently claim to have the bogus Ethernet address 0:0:0:0:0:0. If the bootp/dhcp header htype==0x01 and chaddr=0x000000000000, we'll log the error and not try to respond. Additionally, if a dhcp packet contains a Client ID of 0x01000000000000, we'll do the same. (The latter is not strictly illegal, but seeing it should tip you off that the client is broken or misconfigured.) Thanks to Jeff Ross . --- Some error messages indicating problems with the request packets that should have been produced at debug level 2 or higher were being produced only at debug level 3 or higher; fixed. --- Jeff Ross reports that OPT is not passed from the top-level Makefile to the rest. Fixed, and also changed to pass DEBUG as well (instead of leaving it always set to define DEBUG in the lower-level makefiles). --- If any of the "Must Be Zero" bits in the 'flags' field (in the header) are set, they used to be copied into the reply packet. We'll now clear them before sending a reply. --- Created man pages for dhcpd(8) and dhcpd.conf(5). They're still a bit rough around the edges. --- In the top-level Makefile.in, I rearranged the definitions for CHECK_FILE_ACCESS, TAB-FILE, CONFIG_FILE, HASHTABLESIZE, and LASTBINDIR so that local customizations will be easier to see. Fixed the completely messed-up PID_FILE example definition. --- Rewrote the 'Installation' document to provide a bit more detail. --- Updated sample/dhcpd.conf.sample2 to agree with the man page. --- Moved README.PRINCETON (the readme file that accompanied Princeton patch number 1) to README.PRINCETON1, to follow the convention the other patches are following. Replaced README.PRINCETON contents with generic text explaining what these patches are and where to obtain them. --------------------------------------------------------------------- LEGAL STUFF You may copy, modify, and redistribute these modifications and documentation (the "product"), as long as doing so will not violate any copyrights, patents, or other restrictions that may be imposed on the underlying product by Carnegie Mellon University. The product" is provided "as is" without warranty of any kind, either express or implied, including without limitation any warranty with respect to its mechantability or its fitness for any particular purpose. The entire risk as to the quality and performance of the product is with you. The author, and Princeton University, does not warrant that the functions contained in the product will meet your requirements or that the operation of the product will be uninterrupted or error-free, or that defects in the the product will be corrected.