README for Princeton mods version 5 November 3, 1997 irwin@princeton.edu This file contains information about version 5 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, 2, 3 and 4 already applied. So if you are starting from scratch, first get dhcpd 3.3.7 from CMU, then apply Princeton patches 1, 2, 3 and 4 in order; each of the Princeton patches via available at the URL above. Before applying patch 5, issue the following command: mkdir tools After applying patch 5, issue the following command: chmod 0555 tools/gen-config If you have any local changes to dhcpd, you'll need to reconcile them against these patches. --------------------------------------------------------------------- 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 Changes since PU patch 4: --- Handling of DHCPINFORM packets was wrong. The responses produced could have little to do with the request that was sent. It could crash if the client was not in the bootptab. Processing a DHCPINFORM packet could cause entries in the in-memory bootptab hash tables to become corrupted. It leaked memory for each response packet it sent. I've started working on the problems in dhcp_inform(), but until they're fixed, I've disabled processing of DHCPINFORM packets. When we receive DHCPINFORM packets, we'll ignore them, simply logging them if debuglevel is high enough. --- Some of the calls to hash_Delete() would cause the hashtables to become corrupted. That would eventually lead to attempts to dereference null pointers, or pointer to outside our memory space. This could eventually cause dhcp to die. We call hash_Delete() to remove an element from a hashtable. We pass hash_Delete() a hashcode value, and a pointer to a key which identifies the element to be deleted. hash_Delete() walks the hash table bucket locating all elements that match that key, deleting each one in turn. The problem was that often the hashcode or the key pointer we passed to hash_Delete() were actually ELEMENTS of the ACTUAL hash member were trying to delete. The deletion of that member worked, but then when hash_Delete() continued walking the bucket to find any other members of this hash bucket that matched the key, it was trying to match them to information which only existed in the hash member that was just deleted. Now when calling hash_Delete(), we now pass a *copy* of the hashcode and key ptr (unless the values we are passing are from somewhere *other* than the hash member being deleted anyway. --- Changed umask from 0 to 022 in main.c. The files we create (pidfile, dump files, bindings files) should not be world-writable. Since these files have already been created by earlier runs of the daemon, you may wish to protect them by issuing a chmod 0644 for each of them. --- When dumping a host's record (e.g. to the bindings file), we'll now print one additional line, labelled "expires_time_t". This contains the lease expiration time, the information same as the existing "expires" line we already print, but as a time_t (int) instead of as a string. This change is is for the convenience of programs that parse the bindings file and don't want to have to convert the expiration time from a string back to a time_t. If you have a program that parses the bindings dump file and looks for the existing "expires" line, you should make sure it can distinguish it from the new "expires_time_t" line. --- We now write the pidfile as soon as possible after forking, instead of waiting for the bootptab and dhcpd.conf to be read. This is to make it easier for other processes on your system to see that dhcpd is running. Since you might reasonably start sending USR1 and USR2 signals once you can see the pidfile, but our data is not yet loaded, we'll now ignore those signals until we're ready to handle them. --- Corrected a call to snmp_set() in dhcpcmd.c that caused a core dump on some systems (Donald Matthews ) --- Updated 'Installation' doc to indicate that if you receive errors on the ioctl() calls in init_interface_tab() at startup on an AIX system, try recompiling with BSD defined (Tim Rice, ). --- There was a typo in snmpd/Makefile.in. (Jeff Ross , Chris Tengi ) --- Jeff Ross has contributed a script to help you create bootptab and dhcpd.conf files. It's in tools/gen-config; see the comments in that file for details. --- I removed a debugging message I inadvertantly left in init_interface_tab() in getif.c. --- Corrected a declaration in do_opts() to remove a compiler warning. (Chris Tengi ). --- When debug >= 12, we log the contents of each lastbinding as we read it from disk (init_dhcp() in dhcp.c). However, we did not correctly log the value of the 'expires' and 'last_touch' time. We only logged a single time value for both of these; which value was logged could depend on order of evaluation. Fixed. (This only affecting messages in the log, not actual operation.) --- When dumping bindings, we printed a log message as we started the dump. Now we also print one as we end the dump. --- In create_stub(), added sanity check that the host structure we are passed contains an IP address. --- main.c, readfile.c, dhcp.c, snmp.c, dynamic.c: When calling hash_Lookup(), hash_Insert(), hash_Exists(), or hash_Delete() with hp->iaddr as the key, added some extra parentheses and a cast to make it easier to see what we're passing. --- Throughout the code we were often sloppy in dealing with struct in_addr's, specifying the structure when we really wanted the first (and only) element of the structure, the s_addr. This was sloppy, and has been corrected in various places: * whenever copying a struct in_addr * in data2bind() and bind2data() in perm_utils.c: when converting a binding from/to the representation used in the bindings files, the bcopy() of last_ip from/to the new struct lastbind left out the s_addr element name. * When calling hash_Lookup(), hash_Insert(), hash_Exists(), or hash_Delete(), we were sometimes using hp->iaddr as the key instead of hp->iaddr.s_addr. * dhcp.c: init_dhcp(): when recovering binding from disk, when we compute the hashcode for the struct lastbinding's IP address, we were leaving out the s_addr element name. * when initializing my_ip_addr in main.c * throughout sendreply() in main.c --- dhcp_discover(), dhcp_request(): when create_lease() returned NULL, we leaked the IP address and memory that we tried to allocate. Fixed. (This would happen only under very rare circumstances.) --- There are some additional messages logged when you run with debuglevel > 15 and DEBUG is defined. It's best not to compile with DEBUG defined unless you're really trying to debug the code, for performance reasons. --- Known Bug: We have some endian dependancies that are not yet fixed. Wayne Buttles reports that on his Linux-based server, the lease value returned to client is wrong endian. He reports that even executing the following line: insert_ulong_opt(rpkt,&opt,TAG_DHCP_IPLEASE,10) still causes the WRONG value to be sent on the wire. Endian problem confirmed by Jeff Ross . --------------------------------------------------------------------- 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.