WHAT THIS IS ---------------------------------------------------------- dhcpcd-scriptconfig is a modified version of dhcpcd designed to do all configuration with scripts. The goals are to make a fully extensible DHCP client, to simplify the code inside of the DHCP client itself, and to improve platform independence. These modifications are by Scott Gifford . This software is based on dhcpcd-1.3.20-pl0, maintained by Sergei Viznyuk. It is available at: http://www.phystech.com/download/dhcpcd.html Prior to that, it was maintained by Yoichi Hariguchi. Any bugs in the new version are almost certainly my fault, and neither of these authors should be bothered by them. Because this is a fairly radical change to dhcpcd, and is still quite experimental, I decided to spin it off into a separate project to see how things go. Sergei is doing a great job of maintaining the stable version of dhcpcd, and if you're looking for stability, use his version. WHY THIS IS ---------------------------------------------------------- On the one hand, a DHCP client is a single client program that collects many types of configuration information from a server. On the other hand, UNIX has traditionally been comprised of dozens of small tools, each of which does one thing and does it well. In current DHCP clients, all configuration is performed by a single program. This works well for getting the network interface set up, and acceptably things which are very standard, such as editing /etc/resolv.conf to configure DNS servers, but falls apart for many other tasks. In some cases, such as setting up a default printer or mail relay, that's because there is no single method for configuration which will work on all systems. In other cases, such as passing along information from a DHCP client to a DHCP server, the need is too narrow to justify including this feature in a DHCP client; indeed, if every possible thing somebody might want a DHCP client to do were included as a command-line option, the client would soon grow out of control. The essential problem is a monolithic DHCP client design, where this single program must be all things to all people, and knowledge of how to do every task must be included in the client. Additional functionality must be included in the client, or distributed as a patch. dhcpcd-scriptconfig uses a modular, plug-in design instead. This design lends itself to extensibility. Each configuration task is performed by a single, straightforward shell script (or any other program), independant of any others. Scripts to configure specific software can be distributed seperately from the DHCP client, or even with the software they are configuring, and can be developed independently. Users who want particular functionality can drop a script into the right place to get it, and users who prefer simplicity can avoid all but the basic scripts. This design also contributes to code simplicity, since the DHCP client is only responsible for implementing the DHCP protocol and then running the configuration scripts. Simpler code means less error-prone and more secure code, and allows the DHCP client to follow the UNIX philosophy of do one thing and do it well. The modularity also contributes to cross-platform compatibility. Since everything is configured by scripts, the core DHCP client can be made portable, with non-portable portions confined to a few specific shell scripts. STATUS ---------------------------------------------------------- This exact version of dhcpcd has been running with no issues whatsoever on my personal fileserver and laptop since mid-September of 2001 (right now, that's about 4 months). It does have a few bugs, limitations, and messy code, but I decided to release a version I know worked before making changes. Of course, 4 months one one computer is nothing compared to the testing that the official version of dhcpcd has seen in the real world. Because of this, this code should be considered experimental, and you should not be surprised by weird failures. INSTALLING ---------------------------------------------------------- 1. Build dhcpcd according to the instructions in README.orig 2. If you used a base other than "/" with configure, mkdir /etc/dhcpc 3. Get the appropriate shell scripts for your system (currently, only Linux is supported). 4. Untar the shell scripts in /etc/dhcpc 5. Edit /etc/dhcpc/rc.d/rc and set options as appropriate you need at the top of the script (see RUNNING WITH A MANAGER SCRIPT for more information) 6. By default, these scripts will do some logging, bring up your interface, set up your default route, and edit your /etc/resolv.conf. Scripts are included to do a few other things (see INCLUDED SCRIPTS); if you'd like any of these, create symlinks in the up.d and down.d directories as appropriate. 7. Start dhcpcd. You can either arrange for dhcpcd to be run under supervise (see RUNNING UNDER SUPERVISE), or run: /path/to/dhcpcd [other-opts] -d -m /etc/dhcpc/rc.d/rc [netdev] where [other-opts] are any other options you would pass to dhcpcd (like -h to specify a hostname), and [netdev] is the name of the network device to be configured (for example, eth0). 8. Find problems and report them to me! INCLUDED SCRIPTS ---------------------------------------------------------- dhcpd: This script is for when your machine is both a DHCP client and a server. It edits the configuration of your DHCP server to pass along information from the DHCP client to the DHCP server. Currently, it just passes along DNS configuration information. Set locations of configuration files to be edited and any local nameservers (comma-separated) in the environment variables around line 7. Not used by default. dnscache: Configures your dnscache server to use the DNS servers reported by the DHCP server as its parent servers. Set the location of the configuration file in the environment variable at line 7. Not used by default. donelog: Notes that everything is finished on stdout. Used by default. fail: Simulates a failure. Used for testing. Not used by default. firewall: Configure a simple firewall. Will probably not work for your installation without tweaking (though it works for mine!); it's included as an example. If this machine is a router, set the environment variable of the inside interface at line 9. Not used by default. if: Configure the interface with ifconfig. This or something like it is pretty much necessary. Used by default. netshare: Configure IP masquerading. Set the internal interface for masquerading at line 9, and add any modules used for masquerading at line 11. Not used by default. resolver: Configure /etc/resolv.conf. Set the location of the filename at line 7, although "/etc/resolv.conf" is correct for all systems I've used. Anything in the file specified in RESOLV_DEFAULT will be put in resolv.conf before DHCP generated information. Anything in the file specified in RESOLV_NODHCP will be put in resolv.conf when DHCP goes down, after the contents of $RESOLV_DEFAULT. The file specified in RESOLV_DHCP will be filled with information from the DHCP server, and will be combined with the information in $RESOLV_DEFAULT to form the actual /etc/resolv.conf. Used by default. routes: Configure the default route. This shouldn't require any tweaking. Used by default. saveenv: Save the entire current environment in /etc/dhcpcd-${DEVICE}.env. Only useful for debugging. Not used by default. startlog: Note that the interface has started changing, for the logs. Not used by default. Please contribute your useful scripts! RUNNING WITH A MANAGER SCRIPT ---------------------------------------------------------- A manager script is a shell script which handles configuring the interface and any other tasks which should happen when an interface goes up, down, or changes. New options to support a manager script - - - - - - - - - - - - - - - - - - - - -m manager-script: Connection is managed by manager-script. When the interface comes up, "manager-script up" is run. When the interface goes down, "manager-script down" is run. When anything may have changed, "manager-script change" is run. When the -m option is used, no configuration is done at all; instead, the DHCP protocol is used to get the configuration information, this information is put into a file, and the name of this file is put into the environment variable "DHCP_HOSTINFO". If the information is changing, the name of the old host information file is stored in the environment variable "DHCP_OLDHOSTINFO". Then the script is run as described above. If the manager-script returns 0, all is well and the configuration is considered succesful. If it returns anything else, the configuration is considered to have failed, and the DHCP client acts accordingly. init.d-style scripts - - - - - - - - - - init.d-style scripts are more easily extensible than one big shell script, since functionality can be added or removed simply by creating and symlinking a small script. It also helps make sure everything stays modular, and makes it possible for another software package to "hook in" to the DHCP client by dropping its script in the right place. Just as SysV and Linux do, we implement this with a master script which runs all of the small scripts in the right order. The master script I use is called "rc", and lives in /etc/dhcpcd/eth1/ for my eth1 network card. The first few lines of the script are environment variables you can set yourself. The current variables are boolean, and should be set to "1" to turn them on or "0" to turn them off. They are: VERBOSE: Ask the rc.d scripts to report the major events that are going on. DEBUG: Ask the rc.d scripts to babble on and on about every little thing. ABORT_ON_FAILURE: If any one script returns nonzero, abort the whole process right then and there. Otherwise, continue on. The process of taking an interface down is never aborted, on the assumption that failures aren't that unusual (since we could be taking it down because the card was was removed or the cable unplugged), and that it's probably smart to try to undo everything (if we can't ifconfig down because the card is gone, we definitely don't want to leave the resolv.conf in place for that interface). IGNORE_NONEXISTENT: If a script in up.d, down.d, or change.d has a symlink that points to nothing, don't consider it an error. Otherwise, it is an error, and is handled according to ABORT_ON_FAILURE. After these variables are set, the script sets the PATH to something definite, then reads in and exports the environment variables in the DHCP_HOSTINFO file, and if the DHCP_OLDHOSTINFO file exists, reads those variables in, prepending OLD_ to each of them. The script then determines what it's doing (up, down, or change). It chooses the appropriate directory, "up.d", "down.d", or "change.d". It then runs all of the scripts in that directory which start with a "K" (kill), in numerical order; these scripts should do any cleanup that is necessary (BUG: Should these be run for a change event?). Normally there won't be any K* scripts in up.d or change.d. After that, if the interface is going down, the script exits. If the interface is going up or is changing, we run all of the scripts that start with an "S" (start) in numerical order; these scripts should bring the interface up to a fully operational state. If any of these scripts are nonexistent or return a nonzero status, we behave according to the variables ABORT_ON_FAILURE and IGNORE_NONEXISTENT. After that, if we are still running and haven't aborted from an error, we exit with a status of 0. Writing an init.d-style script for dhcpcd - - - - - - - - - - - - - - - - - - - - - Your script should react to the following environment variables: DEBUG: Print debug information. This information should be useful for tracking down problems that may be caused by your script, and it can be used by you while writing and testing the script. It's useful to wrap your script in lines like this: if [ -n "$DEBUG" ]; then echo "$0: Beginning $1" fi ... if [ -n "$DEBUG" ]; then echo "$0: Ending $1" fi so that at least the start and end of your script will be reported in DEBUG mode. Make sure that all of your DEBUG messages identify what script was running, probably by just starting with "$0: ". VERBOSE: Report basically what you're doing. This information should provide a one-line-or-so summary of what the script did. Make sure that all of your VERBOSE messages identify what script was running, probably by just starting with "$0: ". Your script can expect at least the following environment variables to be set by the DHCP client, if they are provided by the server: IPADDR: The assigned IP address, in dotted-quad notation. NETMASK: The netmask for the assigned IP address, in dotted-quad notation, with ones representing the mask (the standard notation for netmasks). NETWORK: The network number for the assigned IP address. Often, this is IPADDR & NETMASK BROADCAST: The broadcast address for the assigned IP address. Often, this is IPADDR | ~NETMASK. GATEWAY: A comma-separated list of default routers on this subnet. Usually there will be just one item in this list. ROUTE: Static routes. These are in the format: route1address1:route1address2,route2address1:route2address2,... I've never seen these used in practice, so they aren't very well tested. (FIX) HOSTNAME: The hostname you were assigned. DOMAIN: The domain you were assigned. NISDOMAIN: The NIS domain you were assigned. ROOTPATH: Where you should mount your root directory from, if netbooting. (?FIX?) DNS: A comma-separated list of DNS servers you should use. DHCPSID DHCPGIADDR DHCPSIADDR: Settings from the DHCP protocol that you will probably never use. See the RFCs for more information. (FIX) DHCPCHADDR: Client MAC address. DHCPSHADDR: Server MAC address DHCPSNAME: The name of the Server (FIX) LEASETIME RENEWALTIME REBINDTIME LEASEBEGIN: Various times relating to the start and end of your DHCP lease. LEASETIME is the total number of seconds the lease will last for; all others are number of seconds since the Epoch (standard UNIX time). If your script has received a change event, it will have $1 set to "change". In that case, it should inspect any DHCP settings that it cares about, and exit with a status of 0 if no changes are necessary, reporting this fact if VERBOSE is set. Generally, the same script should handle the up, down, and change events. So the next part of your script will probably be a case statement, with "up" or "change" setting things up, or "down" tearing things down. Keep in mind that if your script exits nonzero, it will be treated as a failure, and can cause the whole DHCP process to grind to a halt. So make sure you exit 0 if everything worked, and if something failed, print an error message before exiting with something else. RUNNING UNDER SUPERVISE --------------------------------------------------------- Supervise is a program from Dan Bernstein's daemontools package which gives a consistent management and logging interface to any process which runs as a daemon. Information is available at: http://cr.yp.to/daemontools.html New options to support supervise - - - - - - - - - - - - - - - - -a: Don't detach from terminal and fork into background -v: Log to stdout instead of syslog. Other notes on running under supervise - - - - - - - - - - - - - - - - - - - I run it out of a small script like this: #!/bin/sh exec 2>&1 HOSTNAME=CC312669-A DEVICE=eth1 exec /usr/local/sbin/dhcpcd -h "$HOSTNAME" -d -v -a -m "/etc/dhcpcd/${DEVICE}/rc" "$DEVICE" with a standard multilog setup catching the output and writing the logs. BUGS --------------------------------------------------------- * Scripts' output to stdout isn't captured and syslogged; it works fine under supervise and multilog, though. Workaround: Run dhcpcd >/var/log/dhcpcd.log 2>&1 and look for the output there, or run "dhcpcd |logger 2>&1" * "change" event is only run if IP address changes, not if other information (like DNS servers) changes. Can we even detect when this changes? Not sure... Workaround: Not usually necessary, but if you suspect things may have changed, kill and restart dhcpcd. * There are almost definitely some endian problems on big-endian machines; I've only tested in x86 so far. * Probably others.