aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorDavid E. O'Brien <obrien@FreeBSD.org>1999-02-10 09:10:13 +0000
committerDavid E. O'Brien <obrien@FreeBSD.org>1999-02-10 09:10:13 +0000
commitcd2d014aab8332077aba9b0f6e0d06678fbe1aff (patch)
tree238471ef1d73dff2645de45ab083d2123bf56b83 /contrib
downloadsrc-cd2d014aab8332077aba9b0f6e0d06678fbe1aff.tar.gz
src-cd2d014aab8332077aba9b0f6e0d06678fbe1aff.zip
Virgin import of ISC-DHCP v2.0b1pl6vendor/isc-dhcp/2.0b1-pl.6
Notes
Notes: svn path=/vendor/isc-dhcp/dist/; revision=43829 svn path=/vendor/isc-dhcp/2.0b1-pl.6/; revision=43831; tag=vendor/isc-dhcp/2.0b1-pl.6
Diffstat (limited to 'contrib')
-rw-r--r--contrib/isc-dhcp/CHANGES104
-rw-r--r--contrib/isc-dhcp/README236
-rw-r--r--contrib/isc-dhcp/RELNOTES242
-rw-r--r--contrib/isc-dhcp/client/clparse.c1026
-rw-r--r--contrib/isc-dhcp/client/dhclient-script.8191
-rw-r--r--contrib/isc-dhcp/client/dhclient.8163
-rw-r--r--contrib/isc-dhcp/client/dhclient.c2052
-rw-r--r--contrib/isc-dhcp/client/dhclient.conf36
-rw-r--r--contrib/isc-dhcp/client/dhclient.conf.5543
-rw-r--r--contrib/isc-dhcp/client/dhclient.leases.562
-rwxr-xr-xcontrib/isc-dhcp/client/scripts/freebsd174
-rw-r--r--contrib/isc-dhcp/common/alloc.c329
-rw-r--r--contrib/isc-dhcp/common/bpf.c386
-rw-r--r--contrib/isc-dhcp/common/conflex.c548
-rw-r--r--contrib/isc-dhcp/common/convert.c118
-rw-r--r--contrib/isc-dhcp/common/dhcp-options.5451
-rw-r--r--contrib/isc-dhcp/common/dispatch.c750
-rw-r--r--contrib/isc-dhcp/common/errwarn.c391
-rw-r--r--contrib/isc-dhcp/common/hash.c175
-rw-r--r--contrib/isc-dhcp/common/icmp.c177
-rw-r--r--contrib/isc-dhcp/common/inet.c178
-rw-r--r--contrib/isc-dhcp/common/inet_addr.c150
-rw-r--r--contrib/isc-dhcp/common/memory.c911
-rw-r--r--contrib/isc-dhcp/common/nit.c347
-rw-r--r--contrib/isc-dhcp/common/options.c609
-rw-r--r--contrib/isc-dhcp/common/packet.c311
-rw-r--r--contrib/isc-dhcp/common/parse.c643
-rw-r--r--contrib/isc-dhcp/common/print.c184
-rw-r--r--contrib/isc-dhcp/common/raw.c132
-rw-r--r--contrib/isc-dhcp/common/socket.c256
-rw-r--r--contrib/isc-dhcp/common/tables.c692
-rw-r--r--contrib/isc-dhcp/common/tree.c412
-rw-r--r--contrib/isc-dhcp/common/upf.c298
-rw-r--r--contrib/isc-dhcp/includes/arpa/nameser.h237
-rw-r--r--contrib/isc-dhcp/includes/cdefs.h57
-rw-r--r--contrib/isc-dhcp/includes/cf/freebsd.h89
-rw-r--r--contrib/isc-dhcp/includes/dhcp.h167
-rw-r--r--contrib/isc-dhcp/includes/dhcpd.h947
-rw-r--r--contrib/isc-dhcp/includes/dhctoken.h131
-rw-r--r--contrib/isc-dhcp/includes/hash.h56
-rw-r--r--contrib/isc-dhcp/includes/inet.h52
-rw-r--r--contrib/isc-dhcp/includes/netinet/if_ether.h74
-rw-r--r--contrib/isc-dhcp/includes/netinet/ip.h171
-rw-r--r--contrib/isc-dhcp/includes/netinet/ip_icmp.h182
-rw-r--r--contrib/isc-dhcp/includes/netinet/udp.h47
-rw-r--r--contrib/isc-dhcp/includes/osdep.h220
-rw-r--r--contrib/isc-dhcp/includes/site.h100
-rw-r--r--contrib/isc-dhcp/includes/sysconf.h52
-rw-r--r--contrib/isc-dhcp/includes/tree.h107
49 files changed, 15966 insertions, 0 deletions
diff --git a/contrib/isc-dhcp/CHANGES b/contrib/isc-dhcp/CHANGES
new file mode 100644
index 000000000000..471929701bfb
--- /dev/null
+++ b/contrib/isc-dhcp/CHANGES
@@ -0,0 +1,104 @@
+970609
+
+- Don't trust hostnames provided by client - Win95 allows *spaces* in
+ client-supplied hostnames!
+
+- Be lenient in parsing client-hostname statement in case a bad hostname
+ got recorded.
+
+970607
+
+- Change size_t to ssize_t in return values where a negative number
+ is used to indicate an error.
+
+- Always write out two digits for single-byte quantities in arrays.
+
+- When parsing a lease database, correctly transfer the client
+ hostname and hostname to the memory-resident lease structure.
+
+- If the lease we want to give the client is different than the
+ one it's asking for, and we recognize the one it's asking for as
+ ours, NAK it.
+
+- Only accept a DHCPRELEASE or DHCPNAK if the client supplies an IP
+ address and the lease corresponding to that address is available to
+ that client.
+
+- Make it a warning rather than an error if resolv.conf is missing.
+
+970605
+
+- Add client-hostname token to lexer so that the parser can use it.
+ Fixes a serious lease database bug.
+
+- Disable log message on receipt of short ICMP Echo replies.
+
+970602
+
+- Added DHCP Client scripts for FreeBSD, Solaris, and Linux, but
+ they're not guaranteed to work.
+
+- Added some Cygwin32 (Windows NT/Windows 95) support, but this is not
+ sufficiently complete to be useful yet.
+
+- Updated README
+
+- Put something useful in TODO - formerly it mostly listed projects
+ that were way out on the back burner.
+
+In DHCP Client:
+
+- Add default, supersede, prepend and append option support, so that a
+ client can override or modify server-supplied options, and provide
+ default values if the server provides no values.
+
+- Add reject keyword, so that packets from rogue DHCP or BOOTP servers
+ can be rejected out of hand.
+
+- Added support for booting from BOOTP servers.
+
+- Added BOOTP flag to client lease declaration, to indicated that a
+ particular lease was acquired through a BOOTP server.
+
+- Don't try to do INIT-REBOOT on leases acquired from BOOTP servers.
+
+- Print server's IP address instead of its IP address when logging
+ DHCP/BOOTP messages received by client.
+
+- Fix some bugs in saved lease activation.
+
+- Fix some scripting bugs.
+
+- New sample dhclient.conf script demonstrates new features.
+
+In common code:
+
+- Partially implemented asynchronous DNS lookups.
+
+- Fixed some bugs in dispatch routine.
+
+- Fix date parsing bug that was setting dates forward one day every
+ time dhcpd was restarted (this has been fixed for a while in the 1.0
+ branch).
+
+- Change name-server option name to ien116-name-server so as to reduce
+ the potential for confusion.
+
+DHCP Relay daemon:
+
+- Fixed an operator precedence bug having to do with the broadcast
+ flag.
+
+DHCP Server:
+
+- Add support to record the client-supplied hostname in the lease file,
+ for better readability.
+
+- Fixed a bug in the renewal code that resulted in the server ignoring
+ unicast renewals from non-local subnets. This bug caused some
+ heartburn for Win95 machines.
+
+- Copy ciaddr from saved ciaddr, not from giaddr.
+
+- New -t flag tests /etc/dhcpd.conf for syntax errors.
+
diff --git a/contrib/isc-dhcp/README b/contrib/isc-dhcp/README
new file mode 100644
index 000000000000..c0f45ed9010a
--- /dev/null
+++ b/contrib/isc-dhcp/README
@@ -0,0 +1,236 @@
+ Internet Software Consortium
+ Dynamic Host Configuration Protocol Distribution
+ Version 2, Beta 1, Patchlevel 0
+ December 6, 1997
+
+This is the first Beta release of Version 2 of the Internet Software
+Consortium DHCP Distribution. In version 2.0, this distribution
+includes a DHCP server, a DHCP client, and a BOOTP/DHCP relay agent.
+This beta is believed to be fairly stable. However, DHCP server users
+running a production environment should probably still use version
+1.0, which is more stable, having been in a feature freeze since
+November of 1996.
+
+In this release, the server and relay agent currently work well on
+Digital Alpha OSF/1, SunOS 4.1.4, NetBSD, FreeBSD, BSD/OS and Ultrix.
+They can also be run usefully on Solaris as long as only one broadcast
+network interface is configured. They also runs on QNX and Linux as
+long as only one broadcast network interface is configured and a host
+route is added from that interface to the 255.255.255.255 broadcast
+address. If you are running a Linux 2.0.31 kernel, the DHCP daemons
+may be able to operate on more than one interface.
+
+The DHCP client currently only knows how to configure the network on
+NetBSD, FreeBSD, BSD/os, Linux, Solaris and NextStep. The client
+depends on a system-dependent shell script to do network
+configuration - support for other operating systems is simply a matter
+of porting this shell script to the new platform.
+
+If you wish to run the DHCP Distribution on Linux, please see the
+Linux-specific notes later in this document. If you wish to run on a
+SCO release, please see the SCO-specific notes later in this document.
+You particularly need to read these notes if you intend to support
+Windows 95 clients. If you are running a version of FreeBSD prior to
+2.2, please read the note on FreeBSD. If you are running HP-UX or
+Ultrix, please read the notes for those operating systems below.
+If you are running NeXTSTEP, please see the notes on NeXTSTEP below.
+
+If you start dhcpd and get a message, "no free bpf", that means you
+need to configure the Berkeley Packet Filter into your operating
+system kernel. On NetBSD, FreeBSD and BSD/os, type ``man bpf'' for
+information. On Digital Unix, type ``man pfilt''.
+
+
+ BUILDING THE DHCP DISTRIBUTION
+
+To build the DHCP Distribution, type ``configure''. If configure can
+figure out what sort of system you're running on, it will create a
+custom Makefile for you for that system; otherwise, it will complain.
+If it can't figure out what system you are using, that system is not
+supported - you are on your own.
+
+Once you've run configure, just type ``make'', and after a while you
+should have a dhcp server. If you get compile errors on one of the
+supported systems mentioned earlier, please let us know. If you get
+errors on a system not mentioned above, you will need to do some
+programming or debugging on your own to get the DHCP Distribution working.
+
+ LINUX
+
+There are three big LINUX issues: the all-ones broadcast address,
+Linux 2.1 ip_bootp_agent enabling, and operations with more than one
+network interface.
+
+ BROADCAST
+
+In order for dhcpd to work correctly with picky DHCP clients (e.g.,
+Windows 95), it must be able to send packets with an IP destination
+address of 255.255.255.255. Unfortunately, Linux insists on changing
+255.255.255.255 into the local subnet broadcast address (here, that's
+192.5.5.223). This results in a DHCP protocol violation, and while
+many DHCP clients don't notice the problem, some (e.g., all Microsoft
+DHCP clients) do. Clients that have this problem will appear not to
+see DHCPOFFER messages from the server.
+
+It is possible to work around this problem on some versions of Linux
+by creating a host route from your network interface address to
+255.255.255.255. The command you need to use to do this on Linux
+varies from version to version. The easiest version is:
+
+ route add -host 255.255.255.255 dev eth0
+
+On some older Linux systems, you will get an error if you try to do
+this. On those systems, try adding the following entry to your
+/etc/hosts file:
+
+255.255.255.255 all-ones
+
+Then, try:
+
+ route add -host all-ones dev eth0
+
+Another route that has worked for some users is:
+
+ route add -net 255.255.255.0 dev eth0
+
+If you are not using eth0 as your network interface, you should
+specify the network interface you *are* using in your route command.
+
+ IP BOOTP AGENT
+
+Some versions of the Linux 2.1 kernel apparently prevent dhcpd from
+working unless you enable it by doing the following:
+
+ echo 1 >/proc/sys/net/ipv4/ip_bootp_agent
+
+
+ MULTIPLE INTERFACES
+
+Most older versions of the Linux kernel do not provide a networking
+API that allows dhcpd to operate correctly if the system has more than
+one broadcast network interface. However, Linux 2.0 kernels with
+version numbers greater than or equal to 2.0.31 add an API feature:
+the SO_BINDTODEVICE socket option. If SO_BINDTODEVICE is present, it
+is possible for dhcpd to operate on Linux with more than one network
+interface. In order to take advantage of this, you must be running a
+2.0.31 or greater kernel, and you must have 2.0.31 system headers
+installed *before* you build dhcpd.
+
+NOTE: People have been having problems finding the 2.0.31 kernel
+because it was only available as a prerelease patch. As of October
+17, Linux 2.0.31 is the stable Linux kernel, and is available as a
+kernel distribution rather than as a test patch. With any luck, it
+will be in the latest version of your favourite Linux distribution
+soon.
+
+If you are running a Linux 2.1 kernel, this does not guarantee that you
+have SO_BINDTODEVICE. Linux 2.0.31 was released quite a while after 2.1
+kernel development began. The earliest Linux kernel in the 2.1
+development stream with SO_BINDTODEVICE is version 2.1.68.
+
+We have heard reports that you must still add routes to 255.255.255.255
+in order for the all-ones broadcast to work, even on 2.0.31 kernels.
+In fact, you now need to add a route for each interface. Hopefully
+the Linux kernel gurus will get this straight eventually.
+
+ SCO
+
+SCO has the same problem as Linux (described earlier). The thing is,
+SCO *really* doesn't want to let you add a host route to the all-ones
+broadcast address. One technique that has been successful on some
+versions of SCO is the very bizarre command:
+
+ ifconfig net0 alias 10.1.1.1 netmask 8.0.0.0
+
+Apparently this works because of an interaction between SCO's support
+for network classes and the weird netmask. The 10.* network is just a
+dummy that can generally be assumed to be safe. Don't ask why this
+works. Just try it. If it works for you, great. If not, SCO is
+supposedly adding hooks to support real DHCP service in a future
+release - I have this on good authority from the people at SCO who do
+*their* DHCP server and client.
+
+ HP-UX
+
+HP-UX has the same problem with the all-ones broadcast address that
+SCO and Linux have. One user reported that adding the following to
+/etc/rc.config.d/netconf helped (you may have to modify this to suit
+your local configuration):
+
+INTERFACE_NAME[0]=lan0
+IP_ADDRESS[0]=1.1.1.1
+SUBNET_MASK[0]=255.255.255.0
+BROADCAST_ADDRESS[0]="255.255.255.255"
+LANCONFIG_ARGS[0]="ether"
+DHCP_ENABLE[0]=0
+
+ ULTRIX
+
+Now that we have Ultrix packet filter support, the DHCP Distribution
+on Ultrix should be pretty trouble-free. However, one thing you do
+need to be aware of is that it now requires that the pfilt device be
+configured into your kernel and present in /dev. If you type ``man
+packetfilter'', you will get some information on how to configure your
+kernel for the packet filter (if it isn't already) and how to make an
+entry for it in /dev.
+
+ FreeBSD
+
+Versions of FreeBSD prior to 2.2 have a bug in BPF support in that the
+ethernet driver swaps the ethertype field in the ethernet header
+downstream from BPF, which corrupts the output packet. If you are
+running a version of FreeBSD prior to 2.2, and you find that dhcpd
+can't communicate with its clients, you should #define BROKEN_FREEBSD_BPF
+in site.h and recompile.
+
+ NeXTSTEP
+
+The NeXTSTEP support uses the NeXTSTEP Berkeley Packet Filter
+extension, which is not included in the base NextStep system. You
+must install this extension in order to get dhcpd or dhclient to work.
+
+ SUPPORT
+
+The Internet Software Consortium DHCP server is not a commercial
+product, and is not supported in that sense. However, it has
+attracted a fairly sizable following on the Internet, which means that
+there are a lot of knowledgable users who may be able to help you if
+you get stuck. These people generally read the dhcp-server@fugue.com
+mailing list.
+
+If you are going to use dhcpd, you should probably subscribe to the
+dhcp-server and dhcp-announce mailing lists. If you will be using
+dhclient, you should subscribe to the dhcp-client mailing list.
+PLEASE DO NOT send queries about non-isc clients to the dhcp-client
+mailing list. If you're asking about them on an ISC mailing list,
+it's probably because you're using the ISC DHCP server, so ask there.
+
+Please see http://www.fugue.com/dhcp/lists for details on how to
+subscribe. If you don't have WorldWide Web access, you can send mail
+to dhcp-request@fugue.com and tell me which lists you want to
+subscribe to, but please use the web interface if you can, since I
+have to handle the -request mailing list manually, and I will give you
+the third degree if you make me do your subscription manually.
+
+PLEASE DO NOT SEND REQUESTS FOR SUPPORT DIRECTLY TO ME! The number of
+people using the DHCP Distribution is sufficiently large that if I
+take an interrupt every time any one of those people runs into
+trouble, I will never get any more coding done.
+
+PLEASE DO NOT CALL ME ON THE PHONE FOR SUPPORT! Answering the phone
+takes a lot more of my time and attention than answering email. If you
+do call me on the phone, I will tell you to send email to the mailing
+list, and I won't answer your question, so there's no point in doing
+it.
+
+ BUGS
+
+This release of the DHCP Distribution does not yet contain support for
+DHCPINFORM. Support for DHCPINFORM will be present in the release at
+a later time. DHCPINFORM is somewhat tangential to the main purpose
+of the DHCP protocol, so this probably won't be a major problem for
+most users.
+
+Vendor tags and User tags are not currently supported.
+
+
diff --git a/contrib/isc-dhcp/RELNOTES b/contrib/isc-dhcp/RELNOTES
new file mode 100644
index 000000000000..2cad409c8986
--- /dev/null
+++ b/contrib/isc-dhcp/RELNOTES
@@ -0,0 +1,242 @@
+ Internet Software Consortium
+ Dynamic Host Configuration Protocol Distribution
+ Version 2, Beta 1, Patchlevel 6
+ June 26, 1998
+
+ Release Notes
+
+This is the first Beta release of Version 2 of the Internet Software
+Consortium DHCP Distribution. This beta is believed to be fairly
+stable.
+
+ PLANS
+
+Version 1 of the ISC DHCP Distribution includes just a DHCP Server.
+Version 1 has been in feature freeze since late 1996, and is quite
+stable. This is the release that we would expect most sites to run in
+production.
+
+Version 2 of the ISC DHCP Distribution adds a DHCP Client and a
+DHCP/BOOTP Relay Agent to the DHCP Server that was offered in version
+1.0. In addition, some new capabilities have been added to the
+server:
+
+ - IP addresses are now tested before they are assigned to
+ clients. This allows the DHCP server to detect rogue
+ machines that may have hijacked IP addresses before an IP
+ address conflict can occur.
+
+ - The server may be configured so that some DHCP clients can
+ be excluded from booting.
+
+ - Improved NAKing behaviour, so that clients that are using
+ addresses other than the one the server knows they should be
+ using are disciplined quickly.
+
+This version is now in Beta testing, and is planned for release in
+mid-1998. It has a number of new features, and is the release that we
+would expect sites that want some stability but need the new lease
+testing feature, or need a client or relay agent. Note that it is
+possible to run the Version 1 server with the Version 2 client.
+
+Version 3 of the ISC DHCP Distribution will add Dynamic DNS Support,
+asynchronous DNS query resolution, DHCP Authentication, and possibly
+support for a DHCP Interserver Protocol and live querying of the DHCP
+database. This release is not expected to be stable in the near
+future, and is intended for sites that are in a position to
+experiment, or for sites that desperately need the new features.
+
+ CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 5
+
+- Define some extra DLPI support flags that make DLPI work much better
+ on Solaris.
+
+- Fix inet_aton prototype/declaration to match Internet Software
+ Consortium BIND distribution.
+
+- Document new server-identifier functionality.
+
+ CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 4
+
+- Do not use -Wstrict-prototypes on Solaris with gcc - if the Internet
+ Software Consortium BIND distribution is not installed, this produces
+ errors.
+
+- Actually use the new DLPI support on Solaris - although the code was
+ added in Patchlevel 2, it wasn't enabled (blush).
+
+- Fix a prototype bug that's exposed when DLPI support is enabled on
+ Solaris.
+
+ CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 3
+
+- Fix a makefile botch that prevents the DHCP Distribution from
+ from compiling on Solaris with gcc. Sigh.
+
+ CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 2
+
+- Allow server-identifier in any scope. Use in-scope server
+ identifier option rather than the default, if one exists.
+
+- Delete newlines from abandoned lease reclaimation warning.
+
+- Only release other applicable leases held by a client when the
+ client sends a DHCPREQUEST.
+
+- Fix core dump when find_lease didn't find a lease.
+
+- Update dhcpd.leases man page.
+
+ CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 1
+
+- Use -Wno-char-subscript on Solaris to prevent bogus warnings from
+ gcc on Solaris 2.6.
+
+- Add support for Apple's new Rhapsody operating system.
+
+- Use DLPI on Solaris instead of using the BSD Sockets API.
+
+- Fix two network input buffer overflow problems which could allow an
+ attacker to pervert the stack.
+
+- Fix an ancient typo that could theoretically cause memory
+ corruption.
+
+- Sort abandoned leases in at current time rather than end of time.
+ This allows abandoned leases to be reclaimed if there are no
+ available free leases.
+
+- If a client explicitly requests a lease that's been abandoned, it's
+ probably the system that was answering pings on that address, so let it
+ have the lease.
+
+- Fix a bunch of type conversion errors that are flagged by the Solaris
+ C compiler.
+
+ CHANGES FROM VERSION 2.0 BETA 1 PATCHLEVEL 0
+
+- Fix two potential buffer overflow problems.
+
+- Differentiate between versions of Linux for better success in
+ compiling.
+
+- Fix bug in linux client script regarding routing setup.
+
+- Clarify socket API error message on multiple interfaces.
+
+- Fix broken comparison that was setting IP source address to zero.
+
+- Reclaim abandoned leases if we run out of free leases.
+
+ CHANGES FROM THE DECEMBER 2, 1997 SNAPSHOT
+
+- Use %ld to print pid_t and cast pid_t values to long to avoid
+ inconsistent declarations between different POSIX flavours.
+
+- Add support for ARPHRD_IEEE802 (token ring) hardware type.
+
+- If we own an address and a client requests it, but we can't assign
+ it to that client, we now NAK it so that the client doesn't try to
+ reuse it.
+
+ CHANGES FROM THE JUNE SNAPSHOT
+
+- Support for NeXTstep 3.x and 4.x
+
+- Added man pages for dhcpd.leases, dhclient-script, dhclient.leases
+ and dhclient.conf. Move general documentation of DHCP options into
+ a seperate man page which is referred to by the dhclient.conf and
+ dhcpd.conf man pages.
+
+- Updated README to answer some frequently asked questions.
+
+- Fixed a bug in command-line interface specification in dhclient - it
+ was formerly not possible to specify that only certain interfaces be
+ configured.
+
+- Do not leave client scripts lying around in /tmp after they've been
+ used unless the -D flag is specified.
+
+- Add a new, non-standard, not-guaranteed-to-stay-the-same system
+ configuration status message server which can be used to trigger the
+ client to recheck its address, e.g., after a laptop has been put to
+ sleep and then awakened (this has yet to be documented).
+
+- Fix handling of media selection in the REBOOT phase - previously the
+ media type would not be remembered, which could cause severe delays
+ in reacquiring an address if the default media type was wrong.
+
+- Allocate space for a NUL terminator on the end of client options -
+ this was previously overlooked, and could cause garbage characters
+ to be written to the temporary client script files.
+
+- Use mkstemp if it's available.
+
+- Supply network number and broadcast address to the client script so
+ that on systems that need these values, they don't need to be
+ computed with an awk script.
+
+- Keep a PID file for the client and the relay agent, and have the
+ relay agent background itself by default.
+
+- Add client script for bsd/os, fix many niggling bugs in existing
+ client scripts and add support for static routing tables to all bsd
+ scripts.
+
+- Add a -q option to the client, server and relay agent so that they
+ can be started from /etc/rc scripts without spewing a bunch of
+ garbage on the console. By default, all three daemons still print
+ startup messages, since these are helpful in bug reporting.
+
+- Don't print anything to stderr or stdout after going into
+ background.
+
+- Fix bug where hostname keyword was not being recognized in
+ dhcpd.leases file, resulting in the loss of lease database entries.
+
+- Fix problem on some operating systems where zero-length ifreq
+ structures were being offset incorrectly when scanning the interface
+ list on startup.
+
+- Unless a BOOTP client requests it, never send more than 64 bytes of
+ options.
+
+- Don't ping static leases, since we don't have a lease structure on
+ the heap to work with later.
+
+- Fixed a compile problem on Solaris 2.6.
+
+- Support interface aliases on Solaris.
+
+- Print day and month with leading zero in lease files if less than
+ ten, for easier parsing by perl/sed/awk scripts.
+
+- Never make the lease database world writable, even if dhcpd is
+ invoked with a bogus umask.
+
+- Fix DHCPRELEASE handling (before, addressed would never be
+ released.)
+
+- If there is more than one lease for a particular client on a
+ particular network, find the lease the client is asking for so as to
+ avoid a cycle of NAKs.
+
+- If a BOOTP request is received from a particular client and that
+ client has previously received a DHCP address, make sure that we
+ still find a valid BOOTP lease so that we don't cycle through
+ addresses.
+
+- Remove server-identifier option from documentation, other than to
+ document that it has been deprecated.
+
+- Don't give up if we get an EINTR or EAGAIN while polling or
+ selecting - these return statuses can occur spuriously without
+ indicating a fatal problem.
+
+- Do not select for exceptions, since we don't handle them. This was
+ causing massive CPU consumption on some systems.
+
+- When a DHCP client has been assigned a fixed address but had
+ previously had a lease, it will request the old leased address. In
+ such an event, send a DHCPNAK so that it will discover its new
+ static binding.
diff --git a/contrib/isc-dhcp/client/clparse.c b/contrib/isc-dhcp/client/clparse.c
new file mode 100644
index 000000000000..37fafd378f97
--- /dev/null
+++ b/contrib/isc-dhcp/client/clparse.c
@@ -0,0 +1,1026 @@
+/* clparse.c
+
+ Parser for dhclient config and lease files... */
+
+/*
+ * Copyright (c) 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: clparse.c,v 1.13.2.1 1998/06/25 21:11:27 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+static TIME parsed_time;
+
+struct client_config top_level_config;
+u_int32_t requested_lease_time;
+
+/* client-conf-file :== client-declarations EOF
+ client-declarations :== <nil>
+ | client-declaration
+ | client-declarations client-declaration */
+
+int read_client_conf ()
+{
+ FILE *cfile;
+ char *val;
+ int token;
+ int declaration = 0;
+ struct client_config *config;
+ struct client_state *state;
+ struct interface_info *ip;
+
+ new_parse (path_dhclient_conf);
+
+ /* Set up the initial dhcp option universe. */
+ initialize_universes ();
+
+ /* Initialize the top level client configuration. */
+ memset (&top_level_config, 0, sizeof top_level_config);
+
+ /* Set some defaults... */
+ top_level_config.timeout = 60;
+ top_level_config.select_interval = 0;
+ top_level_config.reboot_timeout = 10;
+ top_level_config.retry_interval = 300;
+ top_level_config.backoff_cutoff = 120;
+ top_level_config.initial_interval = 10;
+ top_level_config.bootp_policy = ACCEPT;
+ top_level_config.script_name = "/etc/dhclient-script";
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_SUBNET_MASK;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_BROADCAST_ADDRESS;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_TIME_OFFSET;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_ROUTERS;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_DOMAIN_NAME;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_DOMAIN_NAME_SERVERS;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_HOST_NAME;
+ requested_lease_time = 7200;
+ top_level_config.send_options [DHO_DHCP_LEASE_TIME].data
+ = (unsigned char *)&requested_lease_time;
+ top_level_config.send_options [DHO_DHCP_LEASE_TIME].len
+ = sizeof requested_lease_time;
+
+ if ((cfile = fopen (path_dhclient_conf, "r")) == NULL)
+ error ("Can't open %s: %m", path_dhclient_conf);
+ do {
+ token = peek_token (&val, cfile);
+ if (token == EOF)
+ break;
+ parse_client_statement (cfile, (struct interface_info *)0,
+ &top_level_config);
+ } while (1);
+ token = next_token (&val, cfile); /* Clear the peek buffer */
+
+ /* Set up state and config structures for clients that don't
+ have per-interface configuration declarations. */
+ config = (struct client_config *)0;
+ for (ip = interfaces; ip; ip = ip -> next) {
+ if (!ip -> client) {
+ ip -> client = (struct client_state *)
+ malloc (sizeof (struct client_state));
+ if (!ip -> client)
+ error ("no memory for client state.");
+ memset (ip -> client, 0, sizeof *(ip -> client));
+ }
+ if (!ip -> client -> config) {
+ if (!config) {
+ config = (struct client_config *)
+ malloc (sizeof (struct client_config));
+ if (!config)
+ error ("no memory for client config.");
+ memcpy (config, &top_level_config,
+ sizeof top_level_config);
+ }
+ ip -> client -> config = config;
+ }
+ }
+
+ return !warnings_occurred;
+}
+
+/* lease-file :== client-lease-statements EOF
+ client-lease-statements :== <nil>
+ | client-lease-statements LEASE client-lease-statement */
+
+void read_client_leases ()
+{
+ FILE *cfile;
+ char *val;
+ int token;
+
+ new_parse (path_dhclient_db);
+
+ /* Open the lease file. If we can't open it, just return -
+ we can safely trust the server to remember our state. */
+ if ((cfile = fopen (path_dhclient_db, "r")) == NULL)
+ return;
+ do {
+ token = next_token (&val, cfile);
+ if (token == EOF)
+ break;
+ if (token != LEASE) {
+ warn ("Corrupt lease file - possible data loss!");
+ skip_to_semi (cfile);
+ break;
+ } else
+ parse_client_lease_statement (cfile, 0);
+
+ } while (1);
+}
+
+/* client-declaration :==
+ SEND option-decl |
+ DEFAULT option-decl |
+ SUPERSEDE option-decl |
+ PREPEND option-decl |
+ APPEND option-decl |
+ hardware-declaration |
+ REQUEST option-list |
+ REQUIRE option-list |
+ TIMEOUT number |
+ RETRY number |
+ REBOOT number |
+ SELECT_TIMEOUT number |
+ SCRIPT string |
+ interface-declaration |
+ LEASE client-lease-statement |
+ ALIAS client-lease-statement */
+
+void parse_client_statement (cfile, ip, config)
+ FILE *cfile;
+ struct interface_info *ip;
+ struct client_config *config;
+{
+ int token;
+ char *val;
+ struct option *option;
+
+ switch (next_token (&val, cfile)) {
+ case SEND:
+ parse_option_decl (cfile, &config -> send_options [0]);
+ return;
+
+ case DEFAULT:
+ option = parse_option_decl (cfile, &config -> defaults [0]);
+ if (option)
+ config -> default_actions [option -> code] =
+ ACTION_DEFAULT;
+ return;
+
+ case SUPERSEDE:
+ option = parse_option_decl (cfile, &config -> defaults [0]);
+ if (option)
+ config -> default_actions [option -> code] =
+ ACTION_SUPERSEDE;
+ return;
+
+ case APPEND:
+ option = parse_option_decl (cfile, &config -> defaults [0]);
+ if (option)
+ config -> default_actions [option -> code] =
+ ACTION_APPEND;
+ return;
+
+ case PREPEND:
+ option = parse_option_decl (cfile, &config -> defaults [0]);
+ if (option)
+ config -> default_actions [option -> code] =
+ ACTION_PREPEND;
+ return;
+
+ case MEDIA:
+ parse_string_list (cfile, &config -> media, 1);
+ return;
+
+ case HARDWARE:
+ if (ip) {
+ parse_hardware_param (cfile, &ip -> hw_address);
+ } else {
+ parse_warn ("hardware address parameter %s",
+ "not allowed here.");
+ skip_to_semi (cfile);
+ }
+ return;
+
+ case REQUEST:
+ config -> requested_option_count =
+ parse_option_list (cfile, config -> requested_options);
+ return;
+
+ case REQUIRE:
+ memset (config -> required_options, 0,
+ sizeof config -> required_options);
+ parse_option_list (cfile, config -> required_options);
+ return;
+
+ case TIMEOUT:
+ parse_lease_time (cfile, &config -> timeout);
+ return;
+
+ case RETRY:
+ parse_lease_time (cfile, &config -> retry_interval);
+ return;
+
+ case SELECT_TIMEOUT:
+ parse_lease_time (cfile, &config -> select_interval);
+ return;
+
+ case REBOOT:
+ parse_lease_time (cfile, &config -> reboot_timeout);
+ return;
+
+ case BACKOFF_CUTOFF:
+ parse_lease_time (cfile, &config -> backoff_cutoff);
+ return;
+
+ case INITIAL_INTERVAL:
+ parse_lease_time (cfile, &config -> initial_interval);
+ return;
+
+ case SCRIPT:
+ config -> script_name = parse_string (cfile);
+ return;
+
+ case INTERFACE:
+ if (ip)
+ parse_warn ("nested interface declaration.");
+ parse_interface_declaration (cfile, config);
+ return;
+
+ case LEASE:
+ parse_client_lease_statement (cfile, 1);
+ return;
+
+ case ALIAS:
+ parse_client_lease_statement (cfile, 2);
+ return;
+
+ case REJECT:
+ parse_reject_statement (cfile, config);
+ return;
+
+ default:
+ parse_warn ("expecting a statement.");
+ skip_to_semi (cfile);
+ break;
+ }
+ token = next_token (&val, cfile);
+ if (token != SEMI) {
+ parse_warn ("semicolon expected.");
+ skip_to_semi (cfile);
+ }
+}
+
+int parse_X (cfile, buf, max)
+ FILE *cfile;
+ u_int8_t *buf;
+ int max;
+{
+ int token;
+ char *val;
+ int len;
+ u_int8_t *s;
+
+ token = peek_token (&val, cfile);
+ if (token == NUMBER_OR_NAME || token == NUMBER) {
+ len = 0;
+ do {
+ token = next_token (&val, cfile);
+ if (token != NUMBER && token != NUMBER_OR_NAME) {
+ parse_warn ("expecting hexadecimal constant.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ convert_num (&buf [len], val, 16, 8);
+ if (len++ > max) {
+ parse_warn ("hexadecimal constant too long.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ token = peek_token (&val, cfile);
+ if (token == COLON)
+ token = next_token (&val, cfile);
+ } while (token == COLON);
+ val = (char *)buf;
+ } else if (token == STRING) {
+ token = next_token (&val, cfile);
+ len = strlen (val);
+ if (len + 1 > max) {
+ parse_warn ("string constant too long.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ memcpy (buf, val, len + 1);
+ } else {
+ parse_warn ("expecting string or hexadecimal data");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ return len;
+}
+
+/* option-list :== option_name |
+ option_list COMMA option_name */
+
+int parse_option_list (cfile, list)
+ FILE *cfile;
+ u_int8_t *list;
+{
+ int ix, i;
+ int token;
+ char *val;
+
+ ix = 0;
+ do {
+ token = next_token (&val, cfile);
+ if (!is_identifier (token)) {
+ parse_warn ("expected option name.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ for (i = 0; i < 256; i++) {
+ if (!strcasecmp (dhcp_options [i].name, val))
+ break;
+ }
+ if (i == 256) {
+ parse_warn ("%s: expected option name.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ list [ix++] = i;
+ if (ix == 256) {
+ parse_warn ("%s: too many options.", val);
+ skip_to_semi (cfile);
+ return 0;
+ }
+ token = next_token (&val, cfile);
+ } while (token == COMMA);
+ if (token != SEMI) {
+ parse_warn ("expecting semicolon.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ return ix;
+}
+
+/* interface-declaration :==
+ INTERFACE string LBRACE client-declarations RBRACE */
+
+void parse_interface_declaration (cfile, outer_config)
+ FILE *cfile;
+ struct client_config *outer_config;
+{
+ int token;
+ char *val;
+
+ struct interface_info dummy_interface, *ip;
+ struct client_state dummy_state;
+ struct client_config dummy_config;
+
+ token = next_token (&val, cfile);
+ if (token != STRING) {
+ parse_warn ("expecting interface name (in quotes).");
+ skip_to_semi (cfile);
+ return;
+ }
+
+ ip = interface_or_dummy (val);
+
+ if (!ip -> client)
+ make_client_state (ip);
+
+ if (!ip -> client -> config)
+ make_client_config (ip, outer_config);
+
+ ip -> flags &= ~INTERFACE_AUTOMATIC;
+ interfaces_requested = 1;
+
+ token = next_token (&val, cfile);
+ if (token != LBRACE) {
+ parse_warn ("expecting left brace.");
+ skip_to_semi (cfile);
+ return;
+ }
+
+ do {
+ token = peek_token (&val, cfile);
+ if (token == EOF) {
+ parse_warn ("unterminated interface declaration.");
+ return;
+ }
+ if (token == RBRACE)
+ break;
+ parse_client_statement (cfile, ip, ip -> client -> config);
+ } while (1);
+ token = next_token (&val, cfile);
+}
+
+struct interface_info *interface_or_dummy (name)
+ char *name;
+{
+ struct interface_info *ip;
+
+ /* Find the interface (if any) that matches the name. */
+ for (ip = interfaces; ip; ip = ip -> next) {
+ if (!strcmp (ip -> name, name))
+ break;
+ }
+
+ /* If it's not a real interface, see if it's on the dummy list. */
+ if (!ip) {
+ for (ip = dummy_interfaces; ip; ip = ip -> next) {
+ if (!strcmp (ip -> name, name))
+ break;
+ }
+ }
+
+ /* If we didn't find an interface, make a dummy interface as
+ a placeholder. */
+ if (!ip) {
+ ip = ((struct interface_info *)malloc (sizeof *ip));
+ if (!ip)
+ error ("Insufficient memory to record interface %s",
+ name);
+ memset (ip, 0, sizeof *ip);
+ strcpy (ip -> name, name);
+ ip -> next = dummy_interfaces;
+ dummy_interfaces = ip;
+ }
+ return ip;
+}
+
+void make_client_state (ip)
+ struct interface_info *ip;
+{
+ ip -> client =
+ ((struct client_state *)malloc (sizeof *(ip -> client)));
+ if (!ip -> client)
+ error ("no memory for state on %s\n", ip -> name);
+ memset (ip -> client, 0, sizeof *(ip -> client));
+}
+
+void make_client_config (ip, config)
+ struct interface_info *ip;
+ struct client_config *config;
+{
+ ip -> client -> config =
+ ((struct client_config *)
+ malloc (sizeof (struct client_config)));
+ if (!ip -> client -> config)
+ error ("no memory for config for %s\n", ip -> name);
+ memset (ip -> client -> config, 0,
+ sizeof *(ip -> client -> config));
+ memcpy (ip -> client -> config, config, sizeof *config);
+}
+
+/* client-lease-statement :==
+ RBRACE client-lease-declarations LBRACE
+
+ client-lease-declarations :==
+ <nil> |
+ client-lease-declaration |
+ client-lease-declarations client-lease-declaration */
+
+
+void parse_client_lease_statement (cfile, is_static)
+ FILE *cfile;
+ int is_static;
+{
+ struct client_lease *lease, *lp, *pl;
+ struct interface_info *ip;
+ int token;
+ char *val;
+
+ token = next_token (&val, cfile);
+ if (token != LBRACE) {
+ parse_warn ("expecting left brace.");
+ skip_to_semi (cfile);
+ return;
+ }
+
+ lease = (struct client_lease *)malloc (sizeof (struct client_lease));
+ if (!lease)
+ error ("no memory for lease.\n");
+ memset (lease, 0, sizeof *lease);
+ lease -> is_static = is_static;
+
+ ip = (struct interface_info *)0;
+
+ do {
+ token = peek_token (&val, cfile);
+ if (token == EOF) {
+ parse_warn ("unterminated lease declaration.");
+ return;
+ }
+ if (token == RBRACE)
+ break;
+ parse_client_lease_declaration (cfile, lease, &ip);
+ } while (1);
+ token = next_token (&val, cfile);
+
+ /* If the lease declaration didn't include an interface
+ declaration that we recognized, it's of no use to us. */
+ if (!ip) {
+ free_client_lease (lease);
+ return;
+ }
+
+ /* Make sure there's a client state structure... */
+ if (!ip -> client)
+ make_client_state (ip);
+
+ /* If this is an alias lease, it doesn't need to be sorted in. */
+ if (is_static == 2) {
+ ip -> client -> alias = lease;
+ return;
+ }
+
+ /* The new lease may supersede a lease that's not the
+ active lease but is still on the lease list, so scan the
+ lease list looking for a lease with the same address, and
+ if we find it, toss it. */
+ pl = (struct client_lease *)0;
+ for (lp = ip -> client -> leases; lp; lp = lp -> next) {
+ if (lp -> address.len == lease -> address.len &&
+ !memcmp (lp -> address.iabuf, lease -> address.iabuf,
+ lease -> address.len)) {
+ if (pl)
+ pl -> next = lp -> next;
+ else
+ ip -> client -> leases = lp -> next;
+ free_client_lease (lp);
+ break;
+ }
+ }
+
+ /* If this is a preloaded lease, just put it on the list of recorded
+ leases - don't make it the active lease. */
+ if (is_static) {
+ lease -> next = ip -> client -> leases;
+ ip -> client -> leases = lease;
+ return;
+ }
+
+ /* The last lease in the lease file on a particular interface is
+ the active lease for that interface. Of course, we don't know
+ what the last lease in the file is until we've parsed the whole
+ file, so at this point, we assume that the lease we just parsed
+ is the active lease for its interface. If there's already
+ an active lease for the interface, and this lease is for the same
+ ip address, then we just toss the old active lease and replace
+ it with this one. If this lease is for a different address,
+ then if the old active lease has expired, we dump it; if not,
+ we put it on the list of leases for this interface which are
+ still valid but no longer active. */
+ if (ip -> client -> active) {
+ if (ip -> client -> active -> expiry < cur_time)
+ free_client_lease (ip -> client -> active);
+ else if (ip -> client -> active -> address.len ==
+ lease -> address.len &&
+ !memcmp (ip -> client -> active -> address.iabuf,
+ lease -> address.iabuf,
+ lease -> address.len))
+ free_client_lease (ip -> client -> active);
+ else {
+ ip -> client -> active -> next =
+ ip -> client -> leases;
+ ip -> client -> leases = ip -> client -> active;
+ }
+ }
+ ip -> client -> active = lease;
+
+ /* phew. */
+}
+
+/* client-lease-declaration :==
+ BOOTP |
+ INTERFACE string |
+ FIXED_ADDR ip_address |
+ FILENAME string |
+ SERVER_NAME string |
+ OPTION option-decl |
+ RENEW time-decl |
+ REBIND time-decl |
+ EXPIRE time-decl */
+
+void parse_client_lease_declaration (cfile, lease, ipp)
+ FILE *cfile;
+ struct client_lease *lease;
+ struct interface_info **ipp;
+{
+ int token;
+ char *val;
+ char *t, *n;
+ struct interface_info *ip;
+
+ switch (next_token (&val, cfile)) {
+ case BOOTP:
+ lease -> is_bootp = 1;
+ break;
+
+ case INTERFACE:
+ token = next_token (&val, cfile);
+ if (token != STRING) {
+ parse_warn ("expecting interface name (in quotes).");
+ skip_to_semi (cfile);
+ break;
+ }
+ ip = interface_or_dummy (val);
+ *ipp = ip;
+ break;
+
+ case FIXED_ADDR:
+ if (!parse_ip_addr (cfile, &lease -> address))
+ return;
+ break;
+
+ case MEDIUM:
+ parse_string_list (cfile, &lease -> medium, 0);
+ return;
+
+ case FILENAME:
+ lease -> filename = parse_string (cfile);
+ return;
+
+ case SERVER_NAME:
+ lease -> server_name = parse_string (cfile);
+ return;
+
+ case RENEW:
+ lease -> renewal = parse_date (cfile);
+ return;
+
+ case REBIND:
+ lease -> rebind = parse_date (cfile);
+ return;
+
+ case EXPIRE:
+ lease -> expiry = parse_date (cfile);
+ return;
+
+ case OPTION:
+ parse_option_decl (cfile, lease -> options);
+ return;
+
+ default:
+ parse_warn ("expecting lease declaration.");
+ skip_to_semi (cfile);
+ break;
+ }
+ token = next_token (&val, cfile);
+ if (token != SEMI) {
+ parse_warn ("expecting semicolon.");
+ skip_to_semi (cfile);
+ }
+}
+
+struct option *parse_option_decl (cfile, options)
+ FILE *cfile;
+ struct option_data *options;
+{
+ char *val;
+ int token;
+ u_int8_t buf [4];
+ u_int8_t hunkbuf [1024];
+ int hunkix = 0;
+ char *vendor;
+ char *fmt;
+ struct universe *universe;
+ struct option *option;
+ struct iaddr ip_addr;
+ u_int8_t *dp;
+ int len;
+ int nul_term = 0;
+
+ token = next_token (&val, cfile);
+ if (!is_identifier (token)) {
+ parse_warn ("expecting identifier after option keyword.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ vendor = malloc (strlen (val) + 1);
+ if (!vendor)
+ error ("no memory for vendor information.");
+ strcpy (vendor, val);
+ token = peek_token (&val, cfile);
+ if (token == DOT) {
+ /* Go ahead and take the DOT token... */
+ token = next_token (&val, cfile);
+
+ /* The next token should be an identifier... */
+ token = next_token (&val, cfile);
+ if (!is_identifier (token)) {
+ parse_warn ("expecting identifier after '.'");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+
+ /* Look up the option name hash table for the specified
+ vendor. */
+ universe = ((struct universe *)
+ hash_lookup (&universe_hash,
+ (unsigned char *)vendor, 0));
+ /* If it's not there, we can't parse the rest of the
+ declaration. */
+ if (!universe) {
+ parse_warn ("no vendor named %s.", vendor);
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ } else {
+ /* Use the default hash table, which contains all the
+ standard dhcp option names. */
+ val = vendor;
+ universe = &dhcp_universe;
+ }
+
+ /* Look up the actual option info... */
+ option = (struct option *)hash_lookup (universe -> hash,
+ (unsigned char *)val, 0);
+
+ /* If we didn't get an option structure, it's an undefined option. */
+ if (!option) {
+ if (val == vendor)
+ parse_warn ("no option named %s", val);
+ else
+ parse_warn ("no option named %s for vendor %s",
+ val, vendor);
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+
+ /* Free the initial identifier token. */
+ free (vendor);
+
+ /* Parse the option data... */
+ do {
+ /* Set a flag if this is an array of a simple type (i.e.,
+ not an array of pairs of IP addresses, or something
+ like that. */
+ int uniform = option -> format [1] == 'A';
+
+ for (fmt = option -> format; *fmt; fmt++) {
+ if (*fmt == 'A')
+ break;
+ switch (*fmt) {
+ case 'X':
+ len = parse_X (cfile, &hunkbuf [hunkix],
+ sizeof hunkbuf - hunkix);
+ hunkix += len;
+ break;
+
+ case 't': /* Text string... */
+ token = next_token (&val, cfile);
+ if (token != STRING) {
+ parse_warn ("expecting string.");
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ len = strlen (val);
+ if (hunkix + len + 1 > sizeof hunkbuf) {
+ parse_warn ("option data buffer %s",
+ "overflow");
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ memcpy (&hunkbuf [hunkix], val, len + 1);
+ nul_term = 1;
+ hunkix += len;
+ break;
+
+ case 'I': /* IP address. */
+ if (!parse_ip_addr (cfile, &ip_addr))
+ return (struct option *)0;
+ len = ip_addr.len;
+ dp = ip_addr.iabuf;
+
+ alloc:
+ if (hunkix + len > sizeof hunkbuf) {
+ parse_warn ("option data buffer %s",
+ "overflow");
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ memcpy (&hunkbuf [hunkix], dp, len);
+ hunkix += len;
+ break;
+
+ case 'L': /* Unsigned 32-bit integer... */
+ case 'l': /* Signed 32-bit integer... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ need_number:
+ parse_warn ("expecting number.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ convert_num (buf, val, 0, 32);
+ len = 4;
+ dp = buf;
+ goto alloc;
+
+ case 's': /* Signed 16-bit integer. */
+ case 'S': /* Unsigned 16-bit integer. */
+ token = next_token (&val, cfile);
+ if (token != NUMBER)
+ goto need_number;
+ convert_num (buf, val, 0, 16);
+ len = 2;
+ dp = buf;
+ goto alloc;
+
+ case 'b': /* Signed 8-bit integer. */
+ case 'B': /* Unsigned 8-bit integer. */
+ token = next_token (&val, cfile);
+ if (token != NUMBER)
+ goto need_number;
+ convert_num (buf, val, 0, 8);
+ len = 1;
+ dp = buf;
+ goto alloc;
+
+ case 'f': /* Boolean flag. */
+ token = next_token (&val, cfile);
+ if (!is_identifier (token)) {
+ parse_warn ("expecting identifier.");
+ bad_flag:
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ if (!strcasecmp (val, "true")
+ || !strcasecmp (val, "on"))
+ buf [0] = 1;
+ else if (!strcasecmp (val, "false")
+ || !strcasecmp (val, "off"))
+ buf [0] = 0;
+ else {
+ parse_warn ("expecting boolean.");
+ goto bad_flag;
+ }
+ len = 1;
+ dp = buf;
+ goto alloc;
+
+ default:
+ warn ("Bad format %c in parse_option_param.",
+ *fmt);
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+ }
+ token = next_token (&val, cfile);
+ } while (*fmt == 'A' && token == COMMA);
+
+ if (token != SEMI) {
+ parse_warn ("semicolon expected.");
+ skip_to_semi (cfile);
+ return (struct option *)0;
+ }
+
+ options [option -> code].data =
+ (unsigned char *)malloc (hunkix + nul_term);
+ if (!options [option -> code].data)
+ error ("out of memory allocating option data.");
+ memcpy (options [option -> code].data, hunkbuf, hunkix + nul_term);
+ options [option -> code].len = hunkix;
+ return option;
+}
+
+void parse_string_list (cfile, lp, multiple)
+ FILE *cfile;
+ struct string_list **lp;
+ int multiple;
+{
+ int token;
+ char *val;
+ struct string_list *cur, *tmp;
+
+ /* Find the last medium in the media list. */
+ if (*lp) {
+ for (cur = *lp; cur -> next; cur = cur -> next)
+ ;
+ } else {
+ cur = (struct string_list *)0;
+ }
+
+ do {
+ token = next_token (&val, cfile);
+ if (token != STRING) {
+ parse_warn ("Expecting media options.");
+ skip_to_semi (cfile);
+ return;
+ }
+
+ tmp = (struct string_list *)malloc (strlen (val) + 1 +
+ sizeof
+ (struct string_list *));
+ if (!tmp)
+ error ("no memory for string list entry.");
+
+ strcpy (tmp -> string, val);
+ tmp -> next = (struct string_list *)0;
+
+ /* Store this medium at the end of the media list. */
+ if (cur)
+ cur -> next = tmp;
+ else
+ *lp = tmp;
+ cur = tmp;
+
+ token = next_token (&val, cfile);
+ } while (multiple && token == COMMA);
+
+ if (token != SEMI) {
+ parse_warn ("expecting semicolon.");
+ skip_to_semi (cfile);
+ }
+}
+
+void parse_reject_statement (cfile, config)
+ FILE *cfile;
+ struct client_config *config;
+{
+ int token;
+ char *val;
+ struct iaddr addr;
+ struct iaddrlist *list;
+
+ do {
+ if (!parse_ip_addr (cfile, &addr)) {
+ parse_warn ("expecting IP address.");
+ skip_to_semi (cfile);
+ return;
+ }
+
+ list = (struct iaddrlist *)malloc (sizeof (struct iaddrlist));
+ if (!list)
+ error ("no memory for reject list!");
+
+ list -> addr = addr;
+ list -> next = config -> reject_list;
+ config -> reject_list = list;
+
+ token = next_token (&val, cfile);
+ } while (token == COMMA);
+
+ if (token != SEMI) {
+ parse_warn ("expecting semicolon.");
+ skip_to_semi (cfile);
+ }
+}
diff --git a/contrib/isc-dhcp/client/dhclient-script.8 b/contrib/isc-dhcp/client/dhclient-script.8
new file mode 100644
index 000000000000..bae59b4634ed
--- /dev/null
+++ b/contrib/isc-dhcp/client/dhclient-script.8
@@ -0,0 +1,191 @@
+.\" dhclient-script.8
+.\"
+.\" Copyright (c) 1997 The Internet Software Consortium.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of The Internet Software Consortium nor the names
+.\" of its contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" This software has been written for the Internet Software Consortium
+.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+.\" Enterprises. To learn more about the Internet Software Consortium,
+.\" see ``http://www.isc.org/isc''. To learn more about Vixie
+.\" Enterprises, see ``http://www.vix.com''.
+.TH dhclient 8
+.SH NAME
+dhclient-script - DHCP client network configuration script
+.SH DESCRIPTION
+The DHCP client network configuration script is invoked from time to
+time by \fBdhclient(8)\fR. This script is used by the dhcp client to
+set each interface's initial configuration prior to requesting an
+address, to test the address once it has been offered, and to set the
+interface's final configuration once a lease has been acquired. If no
+lease is acquired, the script is used to test predefined leases, if
+any, and also called once if no valid lease can be identified.
+.PP
+This script is not meant to be customized by the end user. However,
+the script may not work on particular versions of particular operating
+systems (indeed, no standard script exists for some operating
+systems), so a pioneering user may well need to create a new script or
+modify an existing one. In general, customizations specific to a
+particular computer should be done in the
+.B ETCDIR/dhclient.conf
+script. If you find that you can't make such a customization without
+customizing dhclient.conf, please submit a bug report.
+.SH OPERATION
+When dhclient needs to invoke the client configuration script, it
+writes a shell script into /tmp which defines a variety of variables.
+In all cases, $reason is set to the name of the reason why the script
+has been invoked. The following reasons are currently defined:
+MEDIUM, PREINIT, ARPCHECK, ARPSEND, BOUND, RENEW, REBIND, REBOOT,
+EXPIRE, FAIL and TIMEOUT.
+.PP
+.SH MEDIUM
+The DHCP client is requesting that an interface's media type
+be set. The interface name is passed in $interface, and the media
+type is passed in $medium.
+.SH PREINIT
+The DHCP client is requesting that an interface be configured as
+required in order to send packets prior to receiving an actual
+address. For clients which use the BSD socket library, this means
+configuring the interface with an IP address of 0.0.0.0 and a
+broadcast address of 255.255.255.255. For other clients, it may be
+possible to simply configure the interface up without actually giving
+it an IP address at all. The interface name is passed in $interface,
+and the media type in $medium.
+.PP
+If an IP alias has been declared in dhclient.conf, its address will be
+passed in $alias_ip_address, and that ip alias should be deleted from
+the interface, along with any routes to it.
+.SH ARPSEND
+The DHCP client is requesting that an address that has been offered to
+it be checked to see if somebody else is using it, by sending an ARP
+request for that address. It's not clear how to implement this, so
+no examples exist yet. The IP address to check is passed in
+$new_ip_address, and the interface name is passed in $interface.
+.SH ARPCHECK
+The DHCP client wants to know if a response to the ARP request send
+using ARPCHECK has been received. If one has, the script should exit
+with a nonzero status, indicating that the offered address has already
+been requested and should be declined. $new_ip_address and
+$interface are set as with ARPSEND.
+.SH BOUND
+The DHCP client has done an initial binding to a new address. The
+new ip address is passed in $new_ip_address, and the interface name is
+passed in $interface. The media type is passed in $medium. Any
+options acquired from the server are passed using the option name
+described in \fBdhcp-options\fR, except that dashes ('-') are replaced
+by underscores ('_') in order to make valid shell variables, and the
+variable names start with new_. So for example, the new subnet mask
+would be passed in $new_subnet_mask.
+.PP
+When a binding has been completed, a lot of network parameters are
+likely to need to be set up. A new /etc/resolv.conf needs to be
+created, using the values of $new_domain_name and
+$new_domain_name_servers (which may list more than one server,
+seperated by spaces). A default route should be set using
+$new_routers, and static routes may need to be set up using
+$new_static_routes.
+.PP
+If an IP alias has been declared, it must be set up here. The alias
+IP address will be written as $alias_ip_address, and other DHCP
+options that are set for the alias (e.g., subnet mask) will be passed
+in variables named as described previously except starting with
+$alias_ instead of $new_. Care should be taken that the alias IP
+address not be used if it is identical to the bound IP address
+($new_ip_address), since the other alias parameters may be incorrect
+in this case.
+.SH RENEW
+When a binding has been renewed, the script is called as in BOUND,
+except that in addition to all the variables starting with $new_,
+there is another set of variables starting with $old_. Persistent
+settings that may have changed need to be deleted - for example, if a
+local route to the bound address is being configured, the old local
+route should be deleted. If the default route has changed, the old default
+route should be deleted. If the static routes have changed, the old
+ones should be deleted. Otherwise, processing can be done as with
+BOUND.
+.SH REBIND
+The DHCP client has rebound to a new DHCP server. This can be handled
+as with RENEW, except that if the IP address has changed, the ARP
+table should be cleared.
+.SH REBOOT
+The DHCP client has successfully reacquired its old address after a
+reboot. This can be processed as with BOUND.
+.SH EXPIRE
+The DHCP client has failed to renew its lease or acquire a new one,
+and the lease has expired. The IP address must be relinquished, and
+all related parameters should be deleted, as in RENEW and REBIND.
+.SH FAIL
+The DHCP client has been unable to contact any DHCP servers, and any
+leases that have been tested have not proved to be valid. The
+parameters from the last lease tested should be deconfigured. This
+can be handled in the same way as EXPIRE.
+.SH TIMEOUT
+The DHCP client has been unable to contact any DHCP servers.
+However, an old lease has been identified, and its parameters have
+been passed in as with BOUND. The client configuration script should
+test these parameters and, if it has reason to believe they are valid,
+should exit with a value of zero. If not, it should exit with a
+nonzero value.
+.PP
+The usual way to test a lease is to set up the network as with REBIND
+(since this may be called to test more than one lease) and then ping
+the first router defined in $routers. If a response is received, the
+lease must be valid for the network to which the interface is
+currently connected. It would be more complete to try to ping all of
+the routers listed in $new_routers, as well as those listed in
+$new_static_routes, but current scripts do not do this.
+.SH FILES
+Each operating system should generally have its own script file,
+although the script files for similar operating systems may be similar
+or even identical. The script files included in the Internet
+Software Consortium DHCP distribution appear in the distribution tree
+under client/scripts, and bear the names of the operating systems on
+which they are intended to work.
+.SH BUGS
+If more than one interface is being used, there's no obvious way to
+avoid clashes between server-supplied configuration parameters - for
+example, the stock dhclient-script rewrites /etc/resolv.conf. If
+more than one interface is being configured, /etc/resolv.conf will be
+repeatedly initialized to the values provided by one server, and then
+the other. Assuming the information provided by both servers is
+valid, this shouldn't cause any real problems, but it could be
+confusing.
+.SH SEE ALSO
+dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and
+dhclient.leases(5).
+.SH AUTHOR
+.B dhclient-script(8)
+has been written for the Internet Software Consortium
+by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+Enterprises. To learn more about the Internet Software Consortium,
+see
+.B http://www.vix.com/isc.
+To learn more about Vixie
+Enterprises, see
+.B http://www.vix.com.
diff --git a/contrib/isc-dhcp/client/dhclient.8 b/contrib/isc-dhcp/client/dhclient.8
new file mode 100644
index 000000000000..0406c49137ca
--- /dev/null
+++ b/contrib/isc-dhcp/client/dhclient.8
@@ -0,0 +1,163 @@
+.\" dhclient.8
+.\"
+.\" Copyright (c) 1997 The Internet Software Consortium.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of The Internet Software Consortium nor the names
+.\" of its contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" This software has been written for the Internet Software Consortium
+.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+.\" Enterprises. To learn more about the Internet Software Consortium,
+.\" see ``http://www.isc.org/isc''. To learn more about Vixie
+.\" Enterprises, see ``http://www.vix.com''.
+.TH dhclient 8
+.SH NAME
+dhclient - Dynamic Host Configuration Protocol Client
+.SH SYNOPSIS
+.B dhclient
+[
+.B -p
+.I port
+]
+[
+.B -d
+]
+[
+.I if0
+[
+.I ...ifN
+]
+]
+.SH DESCRIPTION
+The Internet Software Consortium DHCP Client, dhclient, provides a
+means for configuring one or more network interfaces using the Dynamic
+Host Configuration Protocol, BOOTP protocol, or if these protocols
+fail, by statically assigning an address.
+.SH OPERATION
+.PP
+The DHCP protocol allows a host to contact a central server which
+maintains a list of IP addresses which may be assigned on one or more
+subnets. A DHCP client may request an address from this pool, and
+then use it on a temporary basis for communication on network. The
+DHCP protocol also provides a mechanism whereby a client can learn
+important details about the network to which it is attached, such as
+the location of a default router, the location of a name server, and
+so on.
+.PP
+On startup, dhclient reads the
+.IR dhclient.conf
+for configuration instructions. It then gets a list of all the
+network interfaces that are configured in the current system. For
+each interface, it attempts to configure the interface using the DHCP
+protocol.
+.PP
+In order to keep track of leases across system reboots and server
+restarts, dhclient keeps a list of leases it has been assigned in the
+dhclient.leases(5) file. On startup, after reading the dhclient.conf
+file, dhclient reads the dhclient.leases file to refresh its memory
+about what leases it has been assigned.
+.PP
+When a new lease is acquired, it is appended to the end of the
+dhclient.leases file. In order to prevent the file from becoming
+arbitrarily large, from time to time dhclient creates a new
+dhclient.leases file from its in-core lease database. The old version
+of the dhclient.leases file is retained under the name
+.IR dhcpd.leases~
+until the next time dhclient rewrites the database.
+.PP
+Old leases are kept around in case the DHCP server is unavailable when
+dhclient is first invoked (generally during the initial system boot
+process). In that event, old leases from the dhclient.leases file
+which have not yet expired are tested, and if they are determined to
+be valid, they are used until either they expire or the DHCP server
+becomes available.
+.PP
+A mobile host which may sometimes need to access a network on which no
+DHCP server exists may be preloaded with a lease for a fixed
+address on that network. When all attempts to contact a DHCP server
+have failed, dhclient will try to validate the static lease, and if it
+succeeds, will use that lease until it is restarted.
+.PP
+A mobile host may also travel to some networks on which DHCP is not
+available but BOOTP is. In that case, it may be advantageous to
+arrange with the network administrator for an entry on the BOOTP
+database, so that the host can boot quickly on that network rather
+than cycling through the list of old leases.
+.SH COMMAND LINE
+.PP
+The names of the network interfaces that dhclient should attempt to
+configure may be specified on the command line. If no interface names
+are specified on the command line dhclient will identify all network
+interfaces, elimininating non-broadcast interfaces if possible, and
+attempt to configure each interface.
+.PP
+If dhclient should listen and transmit on a port other than the
+standard (port 68), the
+.B -p
+flag may used. It should be followed by the udp port number that
+dhclient should use. This is mostly useful for debugging purposes.
+.PP
+Dhclient will normally run in the foreground until it has configured
+an interface, and then will revert to running in the background.
+To run force dhclient to always run as a foreground process, the
+.B -d
+flag should be specified. This is useful when running dhclient under
+a debugger, or when running it out of inittab on System V systems.
+.PP
+.SH CONFIGURATION
+The syntax of the dhclient.conf(8) file is discussed seperately.
+.SH FILES
+.B ETCDIR/dhclient.conf, DBDIR/dhclient.leases, RUNDIR/dhclient.pid,
+.B DBDIR/dhclient.leases~.
+.SH SEE ALSO
+dhcpd(8), dhcrelay(8), dhclient.conf(5), dhclient.leases(5)
+.SH AUTHOR
+.B dhclient(8)
+has been written for the Internet Software Consortium
+by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+Enterprises. To learn more about the Internet Software Consortium,
+see
+.B http://www.vix.com/isc.
+To learn more about Vixie
+Enterprises, see
+.B http://www.vix.com.
+.PP
+This client was substantially modified and enhanced by Elliot Poger
+for use on Linux while he was working on the MosquitoNet project at
+Stanford.
+.PP
+The current version owes much to Elliot's Linux enhancements, but
+was substantially reorganized and partially rewritten by Ted Lemon
+so as to use the same networking framework that the Internet Software
+Consortium DHCP server uses. Much system-specific configuration code
+was moved into a shell script so that as support for more operating
+systems is added, it will not be necessary to port and maintain
+system-specific configuration code to these operating systems - instead,
+the shell script can invoke the native tools to accomplish the same
+purpose.
+.PP
diff --git a/contrib/isc-dhcp/client/dhclient.c b/contrib/isc-dhcp/client/dhclient.c
new file mode 100644
index 000000000000..eb4d268f9768
--- /dev/null
+++ b/contrib/isc-dhcp/client/dhclient.c
@@ -0,0 +1,2052 @@
+/* dhclient.c
+
+ DHCP Client. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ *
+ * This client was substantially modified and enhanced by Elliot Poger
+ * for use on Linux while he was working on the MosquitoNet project at
+ * Stanford.
+ *
+ * The current version owes much to Elliot's Linux enhancements, but
+ * was substantially reorganized and partially rewritten by Ted Lemon
+ * so as to use the same networking framework that the Internet Software
+ * Consortium DHCP server uses. Much system-specific configuration code
+ * was moved into a shell script so that as support for more operating
+ * systems is added, it will not be necessary to port and maintain
+ * system-specific configuration code to these operating systems - instead,
+ * the shell script can invoke the native tools to accomplish the same
+ * purpose.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: dhclient.c,v 1.44.2.1 1997/12/06 11:24:31 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+TIME cur_time;
+TIME default_lease_time = 43200; /* 12 hours... */
+TIME max_lease_time = 86400; /* 24 hours... */
+struct tree_cache *global_options [256];
+
+char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
+char *path_dhclient_db = _PATH_DHCLIENT_DB;
+char *path_dhclient_pid = _PATH_DHCLIENT_PID;
+
+int interfaces_requested = 0;
+
+int log_perror = 1;
+
+struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
+struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };
+struct in_addr inaddr_any;
+struct sockaddr_in sockaddr_broadcast;
+
+/* ASSERT_STATE() does nothing now; it used to be
+ assert (state_is == state_shouldbe). */
+#define ASSERT_STATE(state_is, state_shouldbe) {}
+
+#ifdef USE_FALLBACK
+struct interface_info fallback_interface;
+#endif
+
+u_int16_t local_port;
+u_int16_t remote_port;
+int log_priority;
+int no_daemon;
+int save_scripts;
+
+static void usage PROTO ((void));
+
+int main (argc, argv, envp)
+ int argc;
+ char **argv, **envp;
+{
+ int i;
+ struct servent *ent;
+ struct interface_info *ip;
+ int seed;
+
+#ifdef SYSLOG_4_2
+ openlog ("dhclient", LOG_NDELAY);
+ log_priority = LOG_DAEMON;
+#else
+ openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);
+#endif
+
+#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__))
+ setlogmask (LOG_UPTO (LOG_INFO));
+#endif
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp (argv [i], "-p")) {
+ if (++i == argc)
+ usage ();
+ local_port = htons (atoi (argv [i]));
+ debug ("binding to user-specified port %d",
+ ntohs (local_port));
+ } else if (!strcmp (argv [i], "-d")) {
+ no_daemon = 1;
+ } else if (!strcmp (argv [i], "-D")) {
+ save_scripts = 1;
+ } else if (argv [i][0] == '-') {
+ usage ();
+ } else {
+ struct interface_info *tmp =
+ ((struct interface_info *)
+ dmalloc (sizeof *tmp, "specified_interface"));
+ if (!tmp)
+ error ("Insufficient memory to %s %s",
+ "record interface", argv [i]);
+ memset (tmp, 0, sizeof *tmp);
+ strcpy (tmp -> name, argv [i]);
+ tmp -> next = interfaces;
+ tmp -> flags = INTERFACE_REQUESTED;
+ interfaces_requested = 1;
+ interfaces = tmp;
+ }
+ }
+ /* Default to the DHCP/BOOTP port. */
+ if (!local_port) {
+ ent = getservbyname ("dhcpc", "udp");
+ if (!ent)
+ local_port = htons (68);
+ else
+ local_port = ent -> s_port;
+#ifndef __CYGWIN32__
+ endservent ();
+#endif
+ }
+ remote_port = htons (ntohs (local_port) - 1); /* XXX */
+
+ /* Get the current time... */
+ GET_TIME (&cur_time);
+
+ sockaddr_broadcast.sin_family = AF_INET;
+ sockaddr_broadcast.sin_port = remote_port;
+ sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
+#ifdef HAVE_SA_LEN
+ sockaddr_broadcast.sin_len = sizeof sockaddr_broadcast;
+#endif
+ inaddr_any.s_addr = INADDR_ANY;
+
+ /* Discover all the network interfaces. */
+ discover_interfaces (DISCOVER_UNCONFIGURED);
+
+ /* Parse the dhclient.conf file. */
+ read_client_conf ();
+
+ /* Parse the lease database. */
+ read_client_leases ();
+
+ /* Rewrite the lease database... */
+ rewrite_client_leases ();
+
+ /* If no broadcast interfaces were discovered, call the script
+ and tell it so. */
+ if (!interfaces) {
+ script_init ((struct interface_info *)0, "NBI",
+ (struct string_list *)0);
+ script_go ((struct interface_info *)0);
+
+ /* Nothing more to do. */
+ exit (0);
+ } else {
+ /* Call the script with the list of interfaces. */
+ for (ip = interfaces; ip; ip = ip -> next) {
+ script_init (ip, "PREINIT", (struct string_list *)0);
+ if (ip -> client -> alias)
+ script_write_params (ip, "alias_",
+ ip -> client -> alias);
+ script_go (ip);
+ }
+ }
+
+ /* At this point, all the interfaces that the script thinks
+ are relevant should be running, so now we once again call
+ discover_interfaces(), and this time ask it to actually set
+ up the interfaces. */
+ discover_interfaces (interfaces_requested
+ ? DISCOVER_REQUESTED
+ : DISCOVER_RUNNING);
+
+ /* Make up a seed for the random number generator from current
+ time plus the sum of the last four bytes of each
+ interface's hardware address interpreted as an integer.
+ Not much entropy, but we're booting, so we're not likely to
+ find anything better. */
+ seed = 0; /* Unfortunately, what's on the stack isn't random. :') */
+ for (ip = interfaces; ip; ip = ip -> next) {
+ int junk;
+ memcpy (&junk,
+ &ip -> hw_address.haddr [ip -> hw_address.hlen -
+ sizeof seed], sizeof seed);
+ seed += junk;
+ }
+ srandom (seed + cur_time);
+
+ /* Start a configuration state machine for each interface. */
+ for (ip = interfaces; ip; ip = ip -> next) {
+ ip -> client -> state = S_INIT;
+ state_reboot (ip);
+ }
+
+ /* Set up the bootp packet handler... */
+ bootp_packet_handler = do_packet;
+
+ /* Start dispatching packets and timeouts... */
+ dispatch ();
+
+ /*NOTREACHED*/
+ return 0;
+}
+
+static void usage ()
+{
+ error ("Usage: dhclient [-c] [-p <port>] [interface]");
+}
+
+void cleanup ()
+{
+}
+
+/* Individual States:
+ *
+ * Each routine is called from the dhclient_state_machine() in one of
+ * these conditions:
+ * -> entering INIT state
+ * -> recvpacket_flag == 0: timeout in this state
+ * -> otherwise: received a packet in this state
+ *
+ * Return conditions as handled by dhclient_state_machine():
+ * Returns 1, sendpacket_flag = 1: send packet, reset timer.
+ * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
+ * Returns 0: finish the nap which was interrupted for no good reason.
+ *
+ * Several per-interface variables are used to keep track of the process:
+ * active_lease: the lease that is being used on the interface
+ * (null pointer if not configured yet).
+ * offered_leases: leases corresponding to DHCPOFFER messages that have
+ * been sent to us by DHCP servers.
+ * acked_leases: leases corresponding to DHCPACK messages that have been
+ * sent to us by DHCP servers.
+ * sendpacket: DHCP packet we're trying to send.
+ * destination: IP address to send sendpacket to
+ * In addition, there are several relevant per-lease variables.
+ * T1_expiry, T2_expiry, lease_expiry: lease milestones
+ * In the active lease, these control the process of renewing the lease;
+ * In leases on the acked_leases list, this simply determines when we
+ * can no longer legitimately use the lease.
+ */
+
+void state_reboot (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ /* If we don't remember an active lease, go straight to INIT. */
+ if (!ip -> client -> active ||
+ ip -> client -> active -> is_bootp) {
+ state_init (ip);
+ return;
+ }
+
+ /* We are in the rebooting state. */
+ ip -> client -> state = S_REBOOTING;
+
+ /* Make a DHCPREQUEST packet, and set appropriate per-interface
+ flags. */
+ make_request (ip, ip -> client -> active);
+ ip -> client -> xid = ip -> client -> packet.xid;
+ ip -> client -> destination = iaddr_broadcast;
+ ip -> client -> first_sending = cur_time;
+ ip -> client -> interval = ip -> client -> config -> initial_interval;
+
+ /* Zap the medium list... */
+ ip -> client -> medium = (struct string_list *)0;
+
+ /* Send out the first DHCPREQUEST packet. */
+ send_request (ip);
+}
+
+/* Called when a lease has completely expired and we've been unable to
+ renew it. */
+
+void state_init (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ ASSERT_STATE(state, S_INIT);
+
+ /* Make a DHCPDISCOVER packet, and set appropriate per-interface
+ flags. */
+ make_discover (ip, ip -> client -> active);
+ ip -> client -> xid = ip -> client -> packet.xid;
+ ip -> client -> destination = iaddr_broadcast;
+ ip -> client -> state = S_SELECTING;
+ ip -> client -> first_sending = cur_time;
+ ip -> client -> interval = ip -> client -> config -> initial_interval;
+
+ /* Add an immediate timeout to cause the first DHCPDISCOVER packet
+ to go out. */
+ send_discover (ip);
+}
+
+/* state_selecting is called when one or more DHCPOFFER packets have been
+ received and a configurable period of time has passed. */
+
+void state_selecting (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ struct client_lease *lp, *next, *picked;
+
+ ASSERT_STATE(state, S_SELECTING);
+
+ /* Cancel state_selecting and send_discover timeouts, since either
+ one could have got us here. */
+ cancel_timeout (state_selecting, ip);
+ cancel_timeout (send_discover, ip);
+
+ /* We have received one or more DHCPOFFER packets. Currently,
+ the only criterion by which we judge leases is whether or
+ not we get a response when we arp for them. */
+ picked = (struct client_lease *)0;
+ for (lp = ip -> client -> offered_leases; lp; lp = next) {
+ next = lp -> next;
+
+ /* Check to see if we got an ARPREPLY for the address
+ in this particular lease. */
+ if (!picked) {
+ script_init (ip, "ARPCHECK", lp -> medium);
+ script_write_params (ip, "check_", lp);
+
+ /* If the ARPCHECK code detects another
+ machine using the offered address, it exits
+ nonzero. We need to send a DHCPDECLINE and
+ toss the lease. */
+ if (script_go (ip)) {
+ make_decline (ip, lp);
+ send_decline (ip);
+ goto freeit;
+ }
+ picked = lp;
+ picked -> next = (struct client_lease *)0;
+ } else {
+ freeit:
+ free_client_lease (lp);
+ }
+ }
+ ip -> client -> offered_leases = (struct client_lease *)0;
+
+ /* If we just tossed all the leases we were offered, go back
+ to square one. */
+ if (!picked) {
+ ip -> client -> state = S_INIT;
+ state_init (ip);
+ return;
+ }
+
+ /* If it was a BOOTREPLY, we can just take the address right now. */
+ if (!picked -> options [DHO_DHCP_MESSAGE_TYPE].len) {
+ ip -> client -> new = picked;
+
+ /* Make up some lease expiry times
+ XXX these should be configurable. */
+ ip -> client -> new -> expiry = cur_time + 12000;
+ ip -> client -> new -> renewal += cur_time + 8000;
+ ip -> client -> new -> rebind += cur_time + 10000;
+
+ ip -> client -> state = S_REQUESTING;
+
+ /* Bind to the address we received. */
+ bind_lease (ip);
+ return;
+ }
+
+ /* Go to the REQUESTING state. */
+ ip -> client -> destination = iaddr_broadcast;
+ ip -> client -> state = S_REQUESTING;
+ ip -> client -> first_sending = cur_time;
+ ip -> client -> interval = ip -> client -> config -> initial_interval;
+
+ /* Make a DHCPREQUEST packet from the lease we picked. */
+ make_request (ip, picked);
+ ip -> client -> xid = ip -> client -> packet.xid;
+
+ /* Toss the lease we picked - we'll get it back in a DHCPACK. */
+ free_client_lease (picked);
+
+ /* Add an immediate timeout to send the first DHCPREQUEST packet. */
+ send_request (ip);
+}
+
+/* state_requesting is called when we receive a DHCPACK message after
+ having sent out one or more DHCPREQUEST packets. */
+
+void dhcpack (packet)
+ struct packet *packet;
+{
+ struct interface_info *ip = packet -> interface;
+ struct client_lease *lease;
+ int i;
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (packet -> interface -> client -> xid != packet -> raw -> xid) {
+ debug ("DHCPACK in wrong transaction.");
+ return;
+ }
+
+ if (ip -> client -> state != S_REBOOTING &&
+ ip -> client -> state != S_REQUESTING &&
+ ip -> client -> state != S_RENEWING &&
+ ip -> client -> state != S_REBINDING) {
+ debug ("DHCPACK in wrong state.");
+ return;
+ }
+
+ note ("DHCPACK from %s", piaddr (packet -> client_addr));
+
+ lease = packet_to_lease (packet);
+ if (!lease) {
+ note ("packet_to_lease failed.");
+ return;
+ }
+
+ ip -> client -> new = lease;
+
+ /* Stop resending DHCPREQUEST. */
+ cancel_timeout (send_request, ip);
+
+ /* Figure out the lease time. */
+ ip -> client -> new -> expiry =
+ getULong (ip -> client ->
+ new -> options [DHO_DHCP_LEASE_TIME].data);
+
+ /* Take the server-provided renewal time if there is one;
+ otherwise figure it out according to the spec. */
+ if (ip -> client -> new -> options [DHO_DHCP_RENEWAL_TIME].len)
+ ip -> client -> new -> renewal =
+ getULong (ip -> client ->
+ new -> options [DHO_DHCP_RENEWAL_TIME].data);
+ else
+ ip -> client -> new -> renewal =
+ ip -> client -> new -> expiry / 2;
+
+ /* Same deal with the rebind time. */
+ if (ip -> client -> new -> options [DHO_DHCP_REBINDING_TIME].len)
+ ip -> client -> new -> rebind =
+ getULong (ip -> client -> new ->
+ options [DHO_DHCP_REBINDING_TIME].data);
+ else
+ ip -> client -> new -> rebind =
+ ip -> client -> new -> renewal +
+ ip -> client -> new -> renewal / 2 +
+ ip -> client -> new -> renewal / 4;
+
+ ip -> client -> new -> expiry += cur_time;
+ ip -> client -> new -> renewal += cur_time;
+ ip -> client -> new -> rebind += cur_time;
+
+ bind_lease (ip);
+}
+
+void bind_lease (ip)
+ struct interface_info *ip;
+{
+ /* Remember the medium. */
+ ip -> client -> new -> medium = ip -> client -> medium;
+
+ /* Write out the new lease. */
+ write_client_lease (ip, ip -> client -> new);
+
+ /* Run the client script with the new parameters. */
+ script_init (ip, (ip -> client -> state == S_REQUESTING
+ ? "BOUND"
+ : (ip -> client -> state == S_RENEWING
+ ? "RENEW"
+ : (ip -> client -> state == S_REBOOTING
+ ? "REBOOT" : "REBIND"))),
+ ip -> client -> new -> medium);
+ if (ip -> client -> active && ip -> client -> state != S_REBOOTING)
+ script_write_params (ip, "old_", ip -> client -> active);
+ script_write_params (ip, "new_", ip -> client -> new);
+ if (ip -> client -> alias)
+ script_write_params (ip, "alias_", ip -> client -> alias);
+ script_go (ip);
+
+ /* Replace the old active lease with the new one. */
+ if (ip -> client -> active)
+ free_client_lease (ip -> client -> active);
+ ip -> client -> active = ip -> client -> new;
+ ip -> client -> new = (struct client_lease *)0;
+
+ /* Set up a timeout to start the renewal process. */
+ add_timeout (ip -> client -> active -> renewal,
+ state_bound, ip);
+
+ note ("bound to %s -- renewal in %d seconds.",
+ piaddr (ip -> client -> active -> address),
+ ip -> client -> active -> renewal - cur_time);
+ ip -> client -> state = S_BOUND;
+ reinitialize_interfaces ();
+ go_daemon ();
+}
+
+/* state_bound is called when we've successfully bound to a particular
+ lease, but the renewal time on that lease has expired. We are
+ expected to unicast a DHCPREQUEST to the server that gave us our
+ original lease. */
+
+void state_bound (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ ASSERT_STATE(state, S_BOUND);
+
+ /* T1 has expired. */
+ make_request (ip, ip -> client -> active);
+ ip -> client -> xid = ip -> client -> packet.xid;
+
+ if (ip -> client -> active ->
+ options [DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
+ memcpy (ip -> client -> destination.iabuf,
+ ip -> client -> active ->
+ options [DHO_DHCP_SERVER_IDENTIFIER].data, 4);
+ ip -> client -> destination.len = 4;
+ } else
+ ip -> client -> destination = iaddr_broadcast;
+
+ ip -> client -> first_sending = cur_time;
+ ip -> client -> interval = ip -> client -> config -> initial_interval;
+ ip -> client -> state = S_RENEWING;
+
+ /* Send the first packet immediately. */
+ send_request (ip);
+}
+
+int commit_leases ()
+{
+ return 0;
+}
+
+int write_lease (lease)
+ struct lease *lease;
+{
+ return 0;
+}
+
+void db_startup ()
+{
+}
+
+void bootp (packet)
+ struct packet *packet;
+{
+ struct iaddrlist *ap;
+
+ if (packet -> raw -> op != BOOTREPLY)
+ return;
+
+ /* If there's a reject list, make sure this packet's sender isn't
+ on it. */
+ for (ap = packet -> interface -> client -> config -> reject_list;
+ ap; ap = ap -> next) {
+ if (addr_eq (packet -> client_addr, ap -> addr)) {
+ note ("BOOTREPLY from %s rejected.",
+ piaddr (ap -> addr));
+ return;
+ }
+ }
+
+ dhcpoffer (packet);
+
+}
+
+void dhcp (packet)
+ struct packet *packet;
+{
+ struct iaddrlist *ap;
+ void (*handler) PROTO ((struct packet *));
+ char *type;
+
+ switch (packet -> packet_type) {
+ case DHCPOFFER:
+ handler = dhcpoffer;
+ type = "DHCPOFFER";
+ break;
+
+ case DHCPNAK:
+ handler = dhcpnak;
+ type = "DHCPNACK";
+ break;
+
+ case DHCPACK:
+ handler = dhcpack;
+ type = "DHCPACK";
+ break;
+
+ default:
+ return;
+ }
+
+ /* If there's a reject list, make sure this packet's sender isn't
+ on it. */
+ for (ap = packet -> interface -> client -> config -> reject_list;
+ ap; ap = ap -> next) {
+ if (addr_eq (packet -> client_addr, ap -> addr)) {
+ note ("%s from %s rejected.",
+ type, piaddr (ap -> addr));
+ return;
+ }
+ }
+ (*handler) (packet);
+}
+
+void dhcpoffer (packet)
+ struct packet *packet;
+{
+ struct interface_info *ip = packet -> interface;
+ struct client_lease *lease, *lp;
+ int i;
+ int arp_timeout_needed, stop_selecting;
+ char *name = (packet -> options [DHO_DHCP_MESSAGE_TYPE].len
+ ? "DHCPOFFER" : "BOOTREPLY");
+ struct iaddrlist *ap;
+
+#ifdef DEBUG_PACKET
+ dump_packet (packet);
+#endif
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (ip -> client -> state != S_SELECTING ||
+ packet -> interface -> client -> xid != packet -> raw -> xid) {
+ debug ("%s in wrong transaction.", name);
+ return;
+ }
+
+ note ("%s from %s", name, piaddr (packet -> client_addr));
+
+
+ /* If this lease doesn't supply the minimum required parameters,
+ blow it off. */
+ for (i = 0; ip -> client -> config -> required_options [i]; i++) {
+ if (!packet -> options [ip -> client -> config ->
+ required_options [i]].len) {
+ note ("%s isn't satisfactory.", name);
+ return;
+ }
+ }
+
+ /* If we've already seen this lease, don't record it again. */
+ for (lease = ip -> client -> offered_leases;
+ lease; lease = lease -> next) {
+ if (lease -> address.len == sizeof packet -> raw -> yiaddr &&
+ !memcmp (lease -> address.iabuf,
+ &packet -> raw -> yiaddr, lease -> address.len)) {
+ debug ("%s already seen.", name);
+ return;
+ }
+ }
+
+ lease = packet_to_lease (packet);
+ if (!lease) {
+ note ("packet_to_lease failed.");
+ return;
+ }
+
+ /* If this lease was acquired through a BOOTREPLY, record that
+ fact. */
+ if (!packet -> options [DHO_DHCP_MESSAGE_TYPE].len)
+ lease -> is_bootp = 1;
+
+ /* Record the medium under which this lease was offered. */
+ lease -> medium = ip -> client -> medium;
+
+ /* Send out an ARP Request for the offered IP address. */
+ script_init (ip, "ARPSEND", lease -> medium);
+ script_write_params (ip, "check_", lease);
+ /* If the script can't send an ARP request without waiting,
+ we'll be waiting when we do the ARPCHECK, so don't wait now. */
+ if (script_go (ip))
+ arp_timeout_needed = 0;
+ else
+ arp_timeout_needed = 2;
+
+ /* Figure out when we're supposed to stop selecting. */
+ stop_selecting = (ip -> client -> first_sending +
+ ip -> client -> config -> select_interval);
+
+ /* If this is the lease we asked for, put it at the head of the
+ list, and don't mess with the arp request timeout. */
+ if (lease -> address.len == ip -> client -> requested_address.len &&
+ !memcmp (lease -> address.iabuf,
+ ip -> client -> requested_address.iabuf,
+ ip -> client -> requested_address.len)) {
+ lease -> next = ip -> client -> offered_leases;
+ ip -> client -> offered_leases = lease;
+ } else {
+ /* If we already have an offer, and arping for this
+ offer would take us past the selection timeout,
+ then don't extend the timeout - just hope for the
+ best. */
+ if (ip -> client -> offered_leases &&
+ (cur_time + arp_timeout_needed) > stop_selecting)
+ arp_timeout_needed = 0;
+
+ /* Put the lease at the end of the list. */
+ lease -> next = (struct client_lease *)0;
+ if (!ip -> client -> offered_leases)
+ ip -> client -> offered_leases = lease;
+ else {
+ for (lp = ip -> client -> offered_leases; lp -> next;
+ lp = lp -> next)
+ ;
+ lp -> next = lease;
+ }
+ }
+
+ /* If we're supposed to stop selecting before we've had time
+ to wait for the ARPREPLY, add some delay to wait for
+ the ARPREPLY. */
+ if (stop_selecting - cur_time < arp_timeout_needed)
+ stop_selecting = cur_time + arp_timeout_needed;
+
+ /* If the selecting interval has expired, go immediately to
+ state_selecting(). Otherwise, time out into
+ state_selecting at the select interval. */
+ if (stop_selecting <= 0)
+ state_selecting (ip);
+ else {
+ add_timeout (stop_selecting, state_selecting, ip);
+ cancel_timeout (send_discover, ip);
+ }
+}
+
+/* Allocate a client_lease structure and initialize it from the parameters
+ in the specified packet. */
+
+struct client_lease *packet_to_lease (packet)
+ struct packet *packet;
+{
+ struct client_lease *lease;
+ int i;
+
+ lease = (struct client_lease *)malloc (sizeof (struct client_lease));
+
+ if (!lease) {
+ warn ("dhcpoffer: no memory to record lease.\n");
+ return (struct client_lease *)0;
+ }
+
+ memset (lease, 0, sizeof *lease);
+
+ /* Copy the lease options. */
+ for (i = 0; i < 256; i++) {
+ if (packet -> options [i].len) {
+ lease -> options [i].data =
+ (unsigned char *)
+ malloc (packet -> options [i].len + 1);
+ if (!lease -> options [i].data) {
+ warn ("dhcpoffer: no memory for option %d\n",
+ i);
+ free_client_lease (lease);
+ return (struct client_lease *)0;
+ } else {
+ memcpy (lease -> options [i].data,
+ packet -> options [i].data,
+ packet -> options [i].len);
+ lease -> options [i].len =
+ packet -> options [i].len;
+ lease -> options [i].data
+ [lease -> options [i].len] = 0;
+ }
+ }
+ }
+
+ lease -> address.len = sizeof (packet -> raw -> yiaddr);
+ memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr,
+ lease -> address.len);
+
+ /* If the server name was filled out, copy it. */
+ if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len ||
+ !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)) &&
+ packet -> raw -> sname [0]) {
+ int len;
+ /* Don't count on the NUL terminator. */
+ for (len = 0; len < 64; len++)
+ if (!packet -> raw -> sname [len])
+ break;
+ lease -> server_name = malloc (len + 1);
+ if (!lease -> server_name) {
+ warn ("dhcpoffer: no memory for filename.\n");
+ free_client_lease (lease);
+ return (struct client_lease *)0;
+ } else {
+ memcpy (lease -> server_name,
+ packet -> raw -> sname, len);
+ lease -> server_name [len] = 0;
+ }
+ }
+
+ /* Ditto for the filename. */
+ if ((!packet -> options [DHO_DHCP_OPTION_OVERLOAD].len ||
+ !(packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)) &&
+ packet -> raw -> file [0]) {
+ int len;
+ /* Don't count on the NUL terminator. */
+ for (len = 0; len < 64; len++)
+ if (!packet -> raw -> file [len])
+ break;
+ lease -> filename = malloc (len + 1);
+ if (!lease -> filename) {
+ warn ("dhcpoffer: no memory for filename.\n");
+ free_client_lease (lease);
+ return (struct client_lease *)0;
+ } else {
+ memcpy (lease -> filename,
+ packet -> raw -> file, len);
+ lease -> filename [len] = 0;
+ }
+ }
+ return lease;
+}
+
+void dhcpnak (packet)
+ struct packet *packet;
+{
+ struct interface_info *ip = packet -> interface;
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (packet -> interface -> client -> xid != packet -> raw -> xid) {
+ debug ("DHCPNAK in wrong transaction.");
+ return;
+ }
+
+ if (ip -> client -> state != S_REBOOTING &&
+ ip -> client -> state != S_REQUESTING &&
+ ip -> client -> state != S_RENEWING &&
+ ip -> client -> state != S_REBINDING) {
+ debug ("DHCPNAK in wrong state.");
+ return;
+ }
+
+ note ("DHCPNAK from %s", piaddr (packet -> client_addr));
+
+ if (!ip -> client -> active) {
+ note ("DHCPNAK with no active lease.\n");
+ return;
+ }
+
+ free_client_lease (ip -> client -> active);
+ ip -> client -> active = (struct client_lease *)0;
+
+ /* Stop sending DHCPREQUEST packets... */
+ cancel_timeout (send_request, ip);
+
+ ip -> client -> state = S_INIT;
+ state_init (ip);
+}
+
+/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
+ one after the right interval has expired. If we don't get an offer by
+ the time we reach the panic interval, call the panic function. */
+
+void send_discover (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ int result;
+ int interval;
+ int increase = 1;
+
+ /* Figure out how long it's been since we started transmitting. */
+ interval = cur_time - ip -> client -> first_sending;
+
+ /* If we're past the panic timeout, call the script and tell it
+ we haven't found anything for this interface yet. */
+ if (interval > ip -> client -> config -> timeout) {
+ state_panic (ip);
+ return;
+ }
+
+ /* If we're selecting media, try the whole list before doing
+ the exponential backoff, but if we've already received an
+ offer, stop looping, because we obviously have it right. */
+ if (!ip -> client -> offered_leases &&
+ ip -> client -> config -> media) {
+ int fail = 0;
+ again:
+ if (ip -> client -> medium) {
+ ip -> client -> medium =
+ ip -> client -> medium -> next;
+ increase = 0;
+ }
+ if (!ip -> client -> medium) {
+ if (fail)
+ error ("No valid media types for %s!",
+ ip -> name);
+ ip -> client -> medium =
+ ip -> client -> config -> media;
+ increase = 1;
+ }
+
+ note ("Trying medium \"%s\" %d",
+ ip -> client -> medium -> string, increase);
+ script_init (ip, "MEDIUM", ip -> client -> medium);
+ if (script_go (ip)) {
+ goto again;
+ }
+ }
+
+ /* If we're supposed to increase the interval, do so. If it's
+ currently zero (i.e., we haven't sent any packets yet), set
+ it to one; otherwise, add to it a random number between
+ zero and two times itself. On average, this means that it
+ will double with every transmission. */
+ if (increase) {
+ if (!ip -> client -> interval)
+ ip -> client -> interval =
+ ip -> client -> config -> initial_interval;
+ else {
+ ip -> client -> interval +=
+ ((random () >> 2) %
+ (2 * ip -> client -> interval));
+ }
+
+ /* Don't backoff past cutoff. */
+ if (ip -> client -> interval >
+ ip -> client -> config -> backoff_cutoff)
+ ip -> client -> interval =
+ ((ip -> client -> config -> backoff_cutoff / 2)
+ + ((random () >> 2)
+ % ip -> client -> interval));
+ } else if (!ip -> client -> interval)
+ ip -> client -> interval =
+ ip -> client -> config -> initial_interval;
+
+ /* If the backoff would take us to the panic timeout, just use that
+ as the interval. */
+ if (cur_time + ip -> client -> interval >
+ ip -> client -> first_sending + ip -> client -> config -> timeout)
+ ip -> client -> interval =
+ (ip -> client -> first_sending +
+ ip -> client -> config -> timeout) - cur_time + 1;
+
+ /* Record the number of seconds since we started sending. */
+ if (interval < 255)
+ ip -> client -> packet.secs = interval;
+ else
+ ip -> client -> packet.secs = 255;
+
+ note ("DHCPDISCOVER on %s to %s port %d interval %ld",
+ ip -> name,
+ inet_ntoa (sockaddr_broadcast.sin_addr),
+ ntohs (sockaddr_broadcast.sin_port), ip -> client -> interval);
+
+ /* Send out a packet. */
+ result = send_packet (ip, (struct packet *)0,
+ &ip -> client -> packet,
+ ip -> client -> packet_length,
+ inaddr_any, &sockaddr_broadcast,
+ (struct hardware *)0);
+ if (result < 0)
+ warn ("send_packet: %m");
+
+ add_timeout (cur_time + ip -> client -> interval, send_discover, ip);
+}
+
+/* state_panic gets called if we haven't received any offers in a preset
+ amount of time. When this happens, we try to use existing leases that
+ haven't yet expired, and failing that, we call the client script and
+ hope it can do something. */
+
+void state_panic (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ struct client_lease *loop = ip -> client -> active;
+ struct client_lease *lp;
+
+ note ("No DHCPOFFERS received.");
+
+ /* We may not have an active lease, but we may have some
+ predefined leases that we can try. */
+ if (!ip -> client -> active && ip -> client -> leases)
+ goto activate_next;
+
+ /* Run through the list of leases and see if one can be used. */
+ while (ip -> client -> active) {
+ if (ip -> client -> active -> expiry > cur_time) {
+ note ("Trying recorded lease %s",
+ piaddr (ip -> client -> active -> address));
+ /* Run the client script with the existing
+ parameters. */
+ script_init (ip, "TIMEOUT",
+ ip -> client -> active -> medium);
+ script_write_params (ip, "new_",
+ ip -> client -> active);
+ if (ip -> client -> alias)
+ script_write_params (ip, "alias_",
+ ip -> client -> alias);
+
+ /* If the old lease is still good and doesn't
+ yet need renewal, go into BOUND state and
+ timeout at the renewal time. */
+ if (!script_go (ip)) {
+ if (cur_time <
+ ip -> client -> active -> renewal) {
+ ip -> client -> state = S_BOUND;
+ note ("bound: renewal in %d seconds.",
+ ip -> client -> active -> renewal
+ - cur_time);
+ add_timeout ((ip -> client ->
+ active -> renewal),
+ state_bound, ip);
+ } else {
+ ip -> client -> state = S_BOUND;
+ note ("bound: immediate renewal.");
+ state_bound (ip);
+ }
+ reinitialize_interfaces ();
+ go_daemon ();
+ return;
+ }
+ }
+
+ /* If there are no other leases, give up. */
+ if (!ip -> client -> leases) {
+ ip -> client -> leases = ip -> client -> active;
+ ip -> client -> active = (struct client_lease *)0;
+ break;
+ }
+
+ activate_next:
+ /* Otherwise, put the active lease at the end of the
+ lease list, and try another lease.. */
+ for (lp = ip -> client -> leases; lp -> next; lp = lp -> next)
+ ;
+ lp -> next = ip -> client -> active;
+ if (lp -> next) {
+ lp -> next -> next = (struct client_lease *)0;
+ }
+ ip -> client -> active = ip -> client -> leases;
+ ip -> client -> leases = ip -> client -> leases -> next;
+
+ /* If we already tried this lease, we've exhausted the
+ set of leases, so we might as well give up for
+ now. */
+ if (ip -> client -> active == loop)
+ break;
+ else if (!loop)
+ loop = ip -> client -> active;
+ }
+
+ /* No leases were available, or what was available didn't work, so
+ tell the shell script that we failed to allocate an address,
+ and try again later. */
+ note ("No working leases in persistent database - sleeping.\n");
+ script_init (ip, "FAIL", (struct string_list *)0);
+ if (ip -> client -> alias)
+ script_write_params (ip, "alias_", ip -> client -> alias);
+ script_go (ip);
+ ip -> client -> state = S_INIT;
+ add_timeout (cur_time + ip -> client -> config -> retry_interval,
+ state_init, ip);
+ go_daemon ();
+}
+
+void send_request (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ int result;
+ int interval;
+ struct sockaddr_in destination;
+ struct in_addr from;
+
+ /* Figure out how long it's been since we started transmitting. */
+ interval = cur_time - ip -> client -> first_sending;
+
+ /* If we're in the INIT-REBOOT or REQUESTING state and we're
+ past the reboot timeout, go to INIT and see if we can
+ DISCOVER an address... */
+ /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
+ means either that we're on a network with no DHCP server,
+ or that our server is down. In the latter case, assuming
+ that there is a backup DHCP server, DHCPDISCOVER will get
+ us a new address, but we could also have successfully
+ reused our old address. In the former case, we're hosed
+ anyway. This is not a win-prone situation. */
+ if ((ip -> client -> state == S_REBOOTING ||
+ ip -> client -> state == S_REQUESTING) &&
+ interval > ip -> client -> config -> reboot_timeout) {
+ cancel:
+ ip -> client -> state = S_INIT;
+ cancel_timeout (send_request, ip);
+ state_init (ip);
+ return;
+ }
+
+ /* If we're in the reboot state, make sure the media is set up
+ correctly. */
+ if (ip -> client -> state == S_REBOOTING &&
+ !ip -> client -> medium &&
+ ip -> client -> active -> medium ) {
+ script_init (ip, "MEDIUM", ip -> client -> active -> medium);
+
+ /* If the medium we chose won't fly, go to INIT state. */
+ if (script_go (ip))
+ goto cancel;
+
+ /* Record the medium. */
+ ip -> client -> medium = ip -> client -> active -> medium;
+ }
+
+ /* If the lease has expired, relinquish the address and go back
+ to the INIT state. */
+ if (ip -> client -> state != S_REQUESTING &&
+ cur_time > ip -> client -> active -> expiry) {
+ /* Run the client script with the new parameters. */
+ script_init (ip, "EXPIRE", (struct string_list *)0);
+ script_write_params (ip, "old_", ip -> client -> active);
+ if (ip -> client -> alias)
+ script_write_params (ip, "alias_",
+ ip -> client -> alias);
+ script_go (ip);
+
+ ip -> client -> state = S_INIT;
+ state_init (ip);
+ return;
+ }
+
+ /* Do the exponential backoff... */
+ if (!ip -> client -> interval)
+ ip -> client -> interval =
+ ip -> client -> config -> initial_interval;
+ else {
+ ip -> client -> interval +=
+ ((random () >> 2) %
+ (2 * ip -> client -> interval));
+ }
+
+ /* Don't backoff past cutoff. */
+ if (ip -> client -> interval >
+ ip -> client -> config -> backoff_cutoff)
+ ip -> client -> interval =
+ ((ip -> client -> config -> backoff_cutoff / 2)
+ + ((random () >> 2)
+ % ip -> client -> interval));
+
+ /* If the backoff would take us to the expiry time, just set the
+ timeout to the expiry time. */
+ if (ip -> client -> state != S_REQUESTING &&
+ cur_time + ip -> client -> interval >
+ ip -> client -> active -> expiry)
+ ip -> client -> interval =
+ ip -> client -> active -> expiry - cur_time + 1;
+
+ /* If the lease T2 time has elapsed, or if we're not yet bound,
+ broadcast the DHCPREQUEST rather than unicasting. */
+ if (ip -> client -> state == S_REQUESTING ||
+ cur_time > ip -> client -> active -> rebind)
+ destination.sin_addr.s_addr = INADDR_BROADCAST;
+ else
+ memcpy (&destination.sin_addr.s_addr,
+ ip -> client -> destination.iabuf,
+ sizeof destination.sin_addr.s_addr);
+ destination.sin_port = remote_port;
+ destination.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ destination.sin_len = sizeof destination;
+#endif
+
+ if (ip -> client -> state != S_REQUESTING)
+ memcpy (&from, ip -> client -> active -> address.iabuf,
+ sizeof from);
+ else
+ from.s_addr = INADDR_ANY;
+
+ /* Record the number of seconds since we started sending. */
+ if (interval < 255)
+ ip -> client -> packet.secs = interval;
+ else
+ ip -> client -> packet.secs = 255;
+
+ note ("DHCPREQUEST on %s to %s port %d", ip -> name,
+ inet_ntoa (destination.sin_addr),
+ ntohs (destination.sin_port));
+
+#ifdef USE_FALLBACK
+ if (destination.sin_addr.s_addr != INADDR_BROADCAST)
+ result = send_fallback (&fallback_interface,
+ (struct packet *)0,
+ &ip -> client -> packet,
+ ip -> client -> packet_length,
+ from, &destination,
+ (struct hardware *)0);
+ else
+#endif /* USE_FALLBACK */
+ /* Send out a packet. */
+ result = send_packet (ip, (struct packet *)0,
+ &ip -> client -> packet,
+ ip -> client -> packet_length,
+ from, &destination,
+ (struct hardware *)0);
+
+ if (result < 0)
+ warn ("send_packet: %m");
+
+ add_timeout (cur_time + ip -> client -> interval,
+ send_request, ip);
+}
+
+void send_decline (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ int result;
+
+ note ("DHCPDECLINE on %s to %s port %d", ip -> name,
+ inet_ntoa (sockaddr_broadcast.sin_addr),
+ ntohs (sockaddr_broadcast.sin_port));
+
+ /* Send out a packet. */
+ result = send_packet (ip, (struct packet *)0,
+ &ip -> client -> packet,
+ ip -> client -> packet_length,
+ inaddr_any, &sockaddr_broadcast,
+ (struct hardware *)0);
+ if (result < 0)
+ warn ("send_packet: %m");
+}
+
+void send_release (ipp)
+ void *ipp;
+{
+ struct interface_info *ip = ipp;
+
+ int result;
+
+ note ("DHCPRELEASE on %s to %s port %d", ip -> name,
+ inet_ntoa (sockaddr_broadcast.sin_addr),
+ ntohs (sockaddr_broadcast.sin_port));
+
+ /* Send out a packet. */
+ result = send_packet (ip, (struct packet *)0,
+ &ip -> client -> packet,
+ ip -> client -> packet_length,
+ inaddr_any, &sockaddr_broadcast,
+ (struct hardware *)0);
+ if (result < 0)
+ warn ("send_packet: %m");
+}
+
+void make_discover (ip, lease)
+ struct interface_info *ip;
+ struct client_lease *lease;
+{
+ struct dhcp_packet *raw;
+ unsigned char discover = DHCPDISCOVER;
+ int i;
+
+ struct tree_cache *options [256];
+ struct tree_cache option_elements [256];
+
+ memset (option_elements, 0, sizeof option_elements);
+ memset (options, 0, sizeof options);
+ memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options [i] = &option_elements [i];
+ options [i] -> value = &discover;
+ options [i] -> len = sizeof discover;
+ options [i] -> buf_size = sizeof discover;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Request the options we want */
+ i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+ options [i] = &option_elements [i];
+ options [i] -> value = ip -> client -> config -> requested_options;
+ options [i] -> len = ip -> client -> config -> requested_option_count;
+ options [i] -> buf_size =
+ ip -> client -> config -> requested_option_count;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* If we had an address, try to get it again. */
+ if (lease) {
+ ip -> client -> requested_address = lease -> address;
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options [i] = &option_elements [i];
+ options [i] -> value = lease -> address.iabuf;
+ options [i] -> len = lease -> address.len;
+ options [i] -> buf_size = lease -> address.len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+ } else {
+ ip -> client -> requested_address.len = 0;
+ }
+
+ /* Send any options requested in the config file. */
+ for (i = 0; i < 256; i++) {
+ if (!options [i] &&
+ ip -> client -> config -> send_options [i].data) {
+ options [i] = &option_elements [i];
+ options [i] -> value = ip -> client -> config ->
+ send_options [i].data;
+ options [i] -> len = ip -> client -> config ->
+ send_options [i].len;
+ options [i] -> buf_size = ip -> client -> config ->
+ send_options [i].len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+ }
+ }
+
+ /* Set up the option buffer... */
+ ip -> client -> packet_length =
+ cons_options ((struct packet *)0, &ip -> client -> packet,
+ options, 0, 0, 0);
+ if (ip -> client -> packet_length < BOOTP_MIN_LEN)
+ ip -> client -> packet_length = BOOTP_MIN_LEN;
+
+ ip -> client -> packet.op = BOOTREQUEST;
+ ip -> client -> packet.htype = ip -> hw_address.htype;
+ ip -> client -> packet.hlen = ip -> hw_address.hlen;
+ ip -> client -> packet.hops = 0;
+ ip -> client -> packet.xid = random ();
+ ip -> client -> packet.secs = 0; /* filled in by send_discover. */
+ ip -> client -> packet.flags = htons (BOOTP_BROADCAST); /* XXX */
+ memset (&(ip -> client -> packet.ciaddr),
+ 0, sizeof ip -> client -> packet.ciaddr);
+ memset (&(ip -> client -> packet.yiaddr),
+ 0, sizeof ip -> client -> packet.yiaddr);
+ memset (&(ip -> client -> packet.siaddr),
+ 0, sizeof ip -> client -> packet.siaddr);
+ memset (&(ip -> client -> packet.giaddr),
+ 0, sizeof ip -> client -> packet.giaddr);
+ memcpy (ip -> client -> packet.chaddr,
+ ip -> hw_address.haddr, ip -> hw_address.hlen);
+
+#ifdef DEBUG_PACKET
+ dump_packet (sendpkt);
+ dump_raw ((unsigned char *)ip -> client -> packet,
+ sendpkt->packet_length);
+#endif
+}
+
+
+void make_request (ip, lease)
+ struct interface_info *ip;
+ struct client_lease *lease;
+{
+ unsigned char request = DHCPREQUEST;
+ int i;
+
+ struct tree_cache *options [256];
+ struct tree_cache option_elements [256];
+
+ memset (options, 0, sizeof options);
+ memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options [i] = &option_elements [i];
+ options [i] -> value = &request;
+ options [i] -> len = sizeof request;
+ options [i] -> buf_size = sizeof request;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Request the options we want */
+ i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+ options [i] = &option_elements [i];
+ options [i] -> value = ip -> client -> config -> requested_options;
+ options [i] -> len = ip -> client -> config -> requested_option_count;
+ options [i] -> buf_size =
+ ip -> client -> config -> requested_option_count;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* If we are requesting an address that hasn't yet been assigned
+ to us, use the DHCP Requested Address option. */
+ if (ip -> client -> state == S_REQUESTING) {
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options [i] = &option_elements [i];
+ options [i] -> value = lease -> options [i].data;
+ options [i] -> len = lease -> options [i].len;
+ options [i] -> buf_size = lease -> options [i].len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+ }
+ if (ip -> client -> state == S_REQUESTING ||
+ ip -> client -> state == S_REBOOTING) {
+ ip -> client -> requested_address = lease -> address;
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options [i] = &option_elements [i];
+ options [i] -> value = lease -> address.iabuf;
+ options [i] -> len = lease -> address.len;
+ options [i] -> buf_size = lease -> address.len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+ } else {
+ ip -> client -> requested_address.len = 0;
+ }
+
+ /* Send any options requested in the config file. */
+ for (i = 0; i < 256; i++) {
+ if (!options [i] &&
+ ip -> client -> config -> send_options [i].data) {
+ options [i] = &option_elements [i];
+ options [i] -> value = ip -> client -> config ->
+ send_options [i].data;
+ options [i] -> len = ip -> client -> config ->
+ send_options [i].len;
+ options [i] -> buf_size = ip -> client -> config ->
+ send_options [i].len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+ }
+ }
+
+ /* Set up the option buffer... */
+ ip -> client -> packet_length =
+ cons_options ((struct packet *)0, &ip -> client -> packet,
+ options, 0, 0, 0);
+ if (ip -> client -> packet_length < BOOTP_MIN_LEN)
+ ip -> client -> packet_length = BOOTP_MIN_LEN;
+
+ ip -> client -> packet.op = BOOTREQUEST;
+ ip -> client -> packet.htype = ip -> hw_address.htype;
+ ip -> client -> packet.hlen = ip -> hw_address.hlen;
+ ip -> client -> packet.hops = 0;
+ ip -> client -> packet.xid = ip -> client -> xid;
+ ip -> client -> packet.secs = 0; /* Filled in by send_request. */
+ ip -> client -> packet.flags = htons (BOOTP_BROADCAST);
+
+ /* If we own the address we're requesting, put it in ciaddr;
+ otherwise set ciaddr to zero. */
+ if (ip -> client -> state == S_BOUND ||
+ ip -> client -> state == S_RENEWING ||
+ ip -> client -> state == S_REBINDING)
+ memcpy (&ip -> client -> packet.ciaddr,
+ lease -> address.iabuf, lease -> address.len);
+ else
+ memset (&ip -> client -> packet.ciaddr, 0,
+ sizeof ip -> client -> packet.ciaddr);
+
+ memset (&ip -> client -> packet.yiaddr, 0,
+ sizeof ip -> client -> packet.yiaddr);
+ memset (&ip -> client -> packet.siaddr, 0,
+ sizeof ip -> client -> packet.siaddr);
+ memset (&ip -> client -> packet.giaddr, 0,
+ sizeof ip -> client -> packet.giaddr);
+ memcpy (ip -> client -> packet.chaddr,
+ ip -> hw_address.haddr, ip -> hw_address.hlen);
+
+#ifdef DEBUG_PACKET
+ dump_packet (sendpkt);
+ dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length);
+#endif
+}
+
+void make_decline (ip, lease)
+ struct interface_info *ip;
+ struct client_lease *lease;
+{
+ unsigned char decline = DHCPDECLINE;
+ int i;
+
+ struct tree_cache *options [256];
+ struct tree_cache message_type_tree;
+ struct tree_cache requested_address_tree;
+ struct tree_cache server_id_tree;
+ struct tree_cache client_id_tree;
+
+ memset (options, 0, sizeof options);
+ memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options [i] = &message_type_tree;
+ options [i] -> value = &decline;
+ options [i] -> len = sizeof decline;
+ options [i] -> buf_size = sizeof decline;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options [i] = &server_id_tree;
+ options [i] -> value = lease -> options [i].data;
+ options [i] -> len = lease -> options [i].len;
+ options [i] -> buf_size = lease -> options [i].len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Send back the address we're declining. */
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options [i] = &requested_address_tree;
+ options [i] -> value = lease -> address.iabuf;
+ options [i] -> len = lease -> address.len;
+ options [i] -> buf_size = lease -> address.len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Send the uid if the user supplied one. */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
+ if (ip -> client -> config -> send_options [i].len) {
+ options [i] = &client_id_tree;
+ options [i] -> value = ip -> client -> config ->
+ send_options [i].data;
+ options [i] -> len = ip -> client -> config ->
+ send_options [i].len;
+ options [i] -> buf_size = ip -> client -> config ->
+ send_options [i].len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+ }
+
+
+ /* Set up the option buffer... */
+ ip -> client -> packet_length =
+ cons_options ((struct packet *)0, &ip -> client -> packet,
+ options, 0, 0, 0);
+ if (ip -> client -> packet_length < BOOTP_MIN_LEN)
+ ip -> client -> packet_length = BOOTP_MIN_LEN;
+
+ ip -> client -> packet.op = BOOTREQUEST;
+ ip -> client -> packet.htype = ip -> hw_address.htype;
+ ip -> client -> packet.hlen = ip -> hw_address.hlen;
+ ip -> client -> packet.hops = 0;
+ ip -> client -> packet.xid = ip -> client -> xid;
+ ip -> client -> packet.secs = 0; /* Filled in by send_request. */
+ ip -> client -> packet.flags = htons (BOOTP_BROADCAST);
+
+ /* ciaddr must always be zero. */
+ memset (&ip -> client -> packet.ciaddr, 0,
+ sizeof ip -> client -> packet.ciaddr);
+ memset (&ip -> client -> packet.yiaddr, 0,
+ sizeof ip -> client -> packet.yiaddr);
+ memset (&ip -> client -> packet.siaddr, 0,
+ sizeof ip -> client -> packet.siaddr);
+ memset (&ip -> client -> packet.giaddr, 0,
+ sizeof ip -> client -> packet.giaddr);
+ memcpy (ip -> client -> packet.chaddr,
+ ip -> hw_address.haddr, ip -> hw_address.hlen);
+
+#ifdef DEBUG_PACKET
+ dump_packet (sendpkt);
+ dump_raw ((unsigned char *)ip -> client -> packet, sendpkt->packet_length);
+#endif
+}
+
+void make_release (ip, lease)
+ struct interface_info *ip;
+ struct client_lease *lease;
+{
+ unsigned char request = DHCPRELEASE;
+ int i;
+
+ struct tree_cache *options [256];
+ struct tree_cache message_type_tree;
+ struct tree_cache requested_address_tree;
+ struct tree_cache server_id_tree;
+
+ memset (options, 0, sizeof options);
+ memset (&ip -> client -> packet, 0, sizeof (ip -> client -> packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options [i] = &message_type_tree;
+ options [i] -> value = &request;
+ options [i] -> len = sizeof request;
+ options [i] -> buf_size = sizeof request;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options [i] = &server_id_tree;
+ options [i] -> value = lease -> options [i].data;
+ options [i] -> len = lease -> options [i].len;
+ options [i] -> buf_size = lease -> options [i].len;
+ options [i] -> timeout = 0xFFFFFFFF;
+ options [i] -> tree = (struct tree *)0;
+
+ /* Set up the option buffer... */
+ ip -> client -> packet_length =
+ cons_options ((struct packet *)0, &ip -> client -> packet,
+ options, 0, 0, 0);
+ if (ip -> client -> packet_length < BOOTP_MIN_LEN)
+ ip -> client -> packet_length = BOOTP_MIN_LEN;
+
+ ip -> client -> packet.op = BOOTREQUEST;
+ ip -> client -> packet.htype = ip -> hw_address.htype;
+ ip -> client -> packet.hlen = ip -> hw_address.hlen;
+ ip -> client -> packet.hops = 0;
+ ip -> client -> packet.xid = ip -> client -> packet.xid;
+ ip -> client -> packet.secs = 0;
+ ip -> client -> packet.flags = 0;
+ memcpy (&ip -> client -> packet.ciaddr,
+ lease -> address.iabuf, lease -> address.len);
+ memset (&ip -> client -> packet.yiaddr, 0,
+ sizeof ip -> client -> packet.yiaddr);
+ memset (&ip -> client -> packet.siaddr, 0,
+ sizeof ip -> client -> packet.siaddr);
+ memset (&ip -> client -> packet.giaddr, 0,
+ sizeof ip -> client -> packet.giaddr);
+ memcpy (ip -> client -> packet.chaddr,
+ ip -> hw_address.haddr, ip -> hw_address.hlen);
+
+#ifdef DEBUG_PACKET
+ dump_packet (sendpkt);
+ dump_raw ((unsigned char *)ip -> client -> packet,
+ ip -> client -> packet_length);
+#endif
+}
+
+void free_client_lease (lease)
+ struct client_lease *lease;
+{
+ int i;
+
+ if (lease -> server_name)
+ free (lease -> server_name);
+ if (lease -> filename)
+ free (lease -> filename);
+ for (i = 0; i < 256; i++) {
+ if (lease -> options [i].len)
+ free (lease -> options [i].data);
+ }
+ free (lease);
+}
+
+FILE *leaseFile;
+
+void rewrite_client_leases ()
+{
+ struct interface_info *ip;
+ struct client_lease *lp;
+
+ if (leaseFile)
+ fclose (leaseFile);
+ leaseFile = fopen (path_dhclient_db, "w");
+ if (!leaseFile)
+ error ("can't create /var/db/dhclient.leases: %m");
+
+ /* Write out all the leases attached to configured interfaces that
+ we know about. */
+ for (ip = interfaces; ip; ip = ip -> next) {
+ for (lp = ip -> client -> leases; lp; lp = lp -> next) {
+ write_client_lease (ip, lp);
+ }
+ if (ip -> client -> active)
+ write_client_lease (ip, ip -> client -> active);
+ }
+
+ /* Write out any leases that are attached to interfaces that aren't
+ currently configured. */
+ for (ip = dummy_interfaces; ip; ip = ip -> next) {
+ for (lp = ip -> client -> leases; lp; lp = lp -> next) {
+ write_client_lease (ip, lp);
+ }
+ if (ip -> client -> active)
+ write_client_lease (ip, ip -> client -> active);
+ }
+ fflush (leaseFile);
+}
+
+void write_client_lease (ip, lease)
+ struct interface_info *ip;
+ struct client_lease *lease;
+{
+ int i;
+ struct tm *t;
+
+ /* If the lease came from the config file, we don't need to stash
+ a copy in the lease database. */
+ if (lease -> is_static)
+ return;
+
+ if (!leaseFile) { /* XXX */
+ leaseFile = fopen (path_dhclient_db, "w");
+ if (!leaseFile)
+ error ("can't create /var/db/dhclient.leases: %m");
+ }
+
+ fprintf (leaseFile, "lease {\n");
+ if (lease -> is_bootp)
+ fprintf (leaseFile, " bootp;\n");
+ fprintf (leaseFile, " interface \"%s\";\n", ip -> name);
+ fprintf (leaseFile, " fixed-address %s;\n",
+ piaddr (lease -> address));
+ if (lease -> filename)
+ fprintf (leaseFile, " filename \"%s\";\n",
+ lease -> filename);
+ if (lease -> server_name)
+ fprintf (leaseFile, " server-name \"%s\";\n",
+ lease -> filename);
+ if (lease -> medium)
+ fprintf (leaseFile, " medium \"%s\";\n",
+ lease -> medium -> string);
+ for (i = 0; i < 256; i++) {
+ if (lease -> options [i].len) {
+ fprintf (leaseFile,
+ " option %s %s;\n",
+ dhcp_options [i].name,
+ pretty_print_option
+ (i, lease -> options [i].data,
+ lease -> options [i].len, 1, 1));
+ }
+ }
+ t = gmtime (&lease -> renewal);
+ fprintf (leaseFile,
+ " renew %d %d/%d/%d %02d:%02d:%02d;\n",
+ t -> tm_wday, t -> tm_year + 1900,
+ t -> tm_mon + 1, t -> tm_mday,
+ t -> tm_hour, t -> tm_min, t -> tm_sec);
+ t = gmtime (&lease -> rebind);
+ fprintf (leaseFile,
+ " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
+ t -> tm_wday, t -> tm_year + 1900,
+ t -> tm_mon + 1, t -> tm_mday,
+ t -> tm_hour, t -> tm_min, t -> tm_sec);
+ t = gmtime (&lease -> expiry);
+ fprintf (leaseFile,
+ " expire %d %d/%d/%d %02d:%02d:%02d;\n",
+ t -> tm_wday, t -> tm_year + 1900,
+ t -> tm_mon + 1, t -> tm_mday,
+ t -> tm_hour, t -> tm_min, t -> tm_sec);
+ fprintf (leaseFile, "}\n");
+ fflush (leaseFile);
+}
+
+/* Variables holding name of script and file pointer for writing to
+ script. Needless to say, this is not reentrant - only one script
+ can be invoked at a time. */
+char scriptName [256];
+FILE *scriptFile;
+
+void script_init (ip, reason, medium)
+ struct interface_info *ip;
+ char *reason;
+ struct string_list *medium;
+{
+ int fd;
+#ifndef HAVE_MKSTEMP
+
+ do {
+#endif
+ strcpy (scriptName, "/tmp/dcsXXXXXX");
+#ifdef HAVE_MKSTEMP
+ fd = mkstemp (scriptName);
+#else
+ mktemp (scriptName);
+ fd = creat (scriptName, 0600);
+ } while (fd < 0);
+#endif
+
+ scriptFile = fdopen (fd, "w");
+ if (!scriptFile)
+ error ("can't write script file: %m");
+ fprintf (scriptFile, "#!/bin/sh\n\n");
+ if (ip) {
+ fprintf (scriptFile, "interface=\"%s\"\n", ip -> name);
+ fprintf (scriptFile, "export interface\n");
+ }
+ if (medium) {
+ fprintf (scriptFile, "medium=\"%s\"\n", medium -> string);
+ fprintf (scriptFile, "export medium\n");
+ }
+ fprintf (scriptFile, "reason=\"%s\"\n", reason);
+ fprintf (scriptFile, "export reason\n");
+}
+
+void script_write_params (ip, prefix, lease)
+ struct interface_info *ip;
+ char *prefix;
+ struct client_lease *lease;
+{
+ int i;
+ u_int8_t dbuf [1500];
+ int len;
+
+ fprintf (scriptFile, "%sip_address=\"%s\"\n",
+ prefix, piaddr (lease -> address));
+ fprintf (scriptFile, "export %sip_address\n", prefix);
+
+ /* For the benefit of Linux (and operating systems which may
+ have similar needs), compute the network address based on
+ the supplied ip address and netmask, if provided. Also
+ compute the broadcast address (the host address all ones
+ broadcast address, not the host address all zeroes
+ broadcast address). */
+
+ if (lease -> options [DHO_SUBNET_MASK].len &&
+ (lease -> options [DHO_SUBNET_MASK].len <
+ sizeof lease -> address.iabuf)) {
+ struct iaddr netmask, subnet, broadcast;
+
+ memcpy (netmask.iabuf,
+ lease -> options [DHO_SUBNET_MASK].data,
+ lease -> options [DHO_SUBNET_MASK].len);
+ netmask.len = lease -> options [DHO_SUBNET_MASK].len;
+
+ subnet = subnet_number (lease -> address, netmask);
+ if (subnet.len) {
+ fprintf (scriptFile, "%snetwork_number=\"%s\";\n",
+ prefix, piaddr (subnet));
+ fprintf (scriptFile, "export %snetwork_number\n",
+ prefix);
+
+ if (!lease -> options [DHO_BROADCAST_ADDRESS].len) {
+ broadcast = broadcast_addr (subnet, netmask);
+ if (broadcast.len) {
+ fprintf (scriptFile,
+ "%s%s=\"%s\";\n", prefix,
+ "broadcast_address",
+ piaddr (broadcast));
+ fprintf (scriptFile,
+ "export %s%s\n", prefix,
+ "broadcast_address");
+ }
+ }
+ }
+ }
+
+ if (lease -> filename) {
+ fprintf (scriptFile, "%sfilename=\"%s\";\n",
+ prefix, lease -> filename);
+ fprintf (scriptFile, "export %sfilename\n", prefix);
+ }
+ if (lease -> server_name) {
+ fprintf (scriptFile, "%sserver_name=\"%s\";\n",
+ prefix, lease -> server_name);
+ fprintf (scriptFile, "export %sserver_name\n", prefix);
+ }
+ for (i = 0; i < 256; i++) {
+ u_int8_t *dp;
+
+ if (ip -> client -> config -> defaults [i].len) {
+ if (lease -> options [i].len) {
+ switch (ip -> client ->
+ config -> default_actions [i]) {
+ case ACTION_DEFAULT:
+ dp = lease -> options [i].data;
+ len = lease -> options [i].len;
+ break;
+ case ACTION_SUPERSEDE:
+ supersede:
+ dp = ip -> client ->
+ config -> defaults [i].data;
+ len = ip -> client ->
+ config -> defaults [i].len;
+ break;
+ case ACTION_PREPEND:
+ len = (ip -> client ->
+ config -> defaults [i].len +
+ lease -> options [i].len);
+ if (len > sizeof dbuf) {
+ warn ("no space to %s %s",
+ "prepend option",
+ dhcp_options [i].name);
+ goto supersede;
+ }
+ dp = dbuf;
+ memcpy (dp,
+ ip -> client ->
+ config -> defaults [i].data,
+ ip -> client ->
+ config -> defaults [i].len);
+ memcpy (dp + ip -> client ->
+ config -> defaults [i].len,
+ lease -> options [i].data,
+ lease -> options [i].len);
+ break;
+ case ACTION_APPEND:
+ len = (ip -> client ->
+ config -> defaults [i].len +
+ lease -> options [i].len);
+ if (len > sizeof dbuf) {
+ warn ("no space to %s %s",
+ "prepend option",
+ dhcp_options [i].name);
+ goto supersede;
+ }
+ dp = dbuf;
+ memcpy (dp,
+ ip -> client ->
+ config -> defaults [i].data,
+ ip -> client ->
+ config -> defaults [i].len);
+ memcpy (dp + ip -> client ->
+ config -> defaults [i].len,
+ lease -> options [i].data,
+ lease -> options [i].len);
+ }
+ } else {
+ dp = ip -> client ->
+ config -> defaults [i].data;
+ len = ip -> client ->
+ config -> defaults [i].len;
+ }
+ } else if (lease -> options [i].len) {
+ len = lease -> options [i].len;
+ dp = lease -> options [i].data;
+ } else {
+ len = 0;
+ }
+ if (len) {
+ char *s = dhcp_option_ev_name (&dhcp_options [i]);
+
+ fprintf (scriptFile, "%s%s=\"%s\"\n", prefix, s,
+ pretty_print_option (i, dp, len, 0, 0));
+ fprintf (scriptFile, "export %s%s\n", prefix, s);
+ }
+ }
+ fprintf (scriptFile, "%sexpiry=\"%d\"\n",
+ prefix, (int)lease -> expiry); /* XXX */
+ fprintf (scriptFile, "export %sexpiry\n", prefix);
+}
+
+int script_go (ip)
+ struct interface_info *ip;
+{
+ int rval;
+
+ if (ip)
+ fprintf (scriptFile, "%s\n",
+ ip -> client -> config -> script_name);
+ else
+ fprintf (scriptFile, "%s\n",
+ top_level_config.script_name);
+ fprintf (scriptFile, "exit $?\n");
+ fclose (scriptFile);
+ chmod (scriptName, 0700);
+ rval = system (scriptName);
+ if (!save_scripts)
+ unlink (scriptName);
+ return rval;
+}
+
+char *dhcp_option_ev_name (option)
+ struct option *option;
+{
+ static char evbuf [256];
+ int i;
+
+ if (strlen (option -> name) + 1 > sizeof evbuf)
+ error ("option %s name is larger than static buffer.");
+ for (i = 0; option -> name [i]; i++) {
+ if (option -> name [i] == '-')
+ evbuf [i] = '_';
+ else
+ evbuf [i] = option -> name [i];
+ }
+
+ evbuf [i] = 0;
+ return evbuf;
+}
+
+void go_daemon ()
+{
+ static int state = 0;
+ int pid;
+
+ /* Don't become a daemon if the user requested otherwise. */
+ if (no_daemon) {
+ write_client_pid_file ();
+ return;
+ }
+
+ /* Only do it once. */
+ if (state)
+ return;
+ state = 1;
+
+ /* Stop logging to stderr... */
+ log_perror = 0;
+
+ /* Become a daemon... */
+ if ((pid = fork ()) < 0)
+ error ("Can't fork daemon: %m");
+ else if (pid)
+ exit (0);
+ /* Become session leader and get pid... */
+ pid = setsid ();
+
+ write_client_pid_file ();
+}
+
+void write_client_pid_file ()
+{
+ FILE *pf;
+ int pfdesc;
+
+ pfdesc = open (path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+
+ if (pfdesc < 0) {
+ warn ("Can't create %s: %m", path_dhclient_pid);
+ return;
+ }
+
+ pf = fdopen (pfdesc, "w");
+ if (!pf)
+ warn ("Can't fdopen %s: %m", path_dhclient_pid);
+ else {
+ fprintf (pf, "%ld\n", (long)getpid ());
+ fclose (pf);
+ }
+}
diff --git a/contrib/isc-dhcp/client/dhclient.conf b/contrib/isc-dhcp/client/dhclient.conf
new file mode 100644
index 000000000000..147e0045a5d8
--- /dev/null
+++ b/contrib/isc-dhcp/client/dhclient.conf
@@ -0,0 +1,36 @@
+send host-name "andare.fugue.com";
+send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
+send dhcp-lease-time 3600;
+supersede domain-name "fugue.com home.vix.com";
+prepend domain-name-servers 127.0.0.1;
+request subnet-mask, broadcast-address, time-offset, routers,
+ domain-name, domain-name-servers, host-name;
+require subnet-mask, domain-name-servers;
+timeout 60;
+retry 60;
+reboot 10;
+select-timeout 5;
+initial-interval 2;
+script "/etc/dhclient-script";
+media "-link0 -link1 -link2", "link0 link1";
+reject 192.33.137.209;
+
+alias {
+ interface "ep0";
+ fixed-address 192.5.5.213;
+ option subnet-mask 255.255.255.255;
+}
+
+lease {
+ interface "ep0";
+ fixed-address 192.33.137.200;
+ medium "link0 link1";
+ option host-name "andare.swiftmedia.com";
+ option subnet-mask 255.255.255.0;
+ option broadcast-address 192.33.137.255;
+ option routers 192.33.137.250;
+ option domain-name-servers 127.0.0.1;
+ renew 2 2000/1/12 00:00:01;
+ rebind 2 2000/1/12 00:00:01;
+ expire 2 2000/1/12 00:00:01;
+}
diff --git a/contrib/isc-dhcp/client/dhclient.conf.5 b/contrib/isc-dhcp/client/dhclient.conf.5
new file mode 100644
index 000000000000..c5af648cf912
--- /dev/null
+++ b/contrib/isc-dhcp/client/dhclient.conf.5
@@ -0,0 +1,543 @@
+.\" dhclient.conf.5
+.\"
+.\" Copyright (c) 1997 The Internet Software Consortium.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of The Internet Software Consortium nor the names
+.\" of its contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" This software has been written for the Internet Software Consortium
+.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+.\" Enterprises. To learn more about the Internet Software Consortium,
+.\" see ``http://www.isc.org/isc''. To learn more about Vixie
+.\" Enterprises, see ``http://www.vix.com''.
+.TH dhclient.conf 5
+.SH NAME
+dhclient.conf - DHCP client configuration file
+.SH DESCRIPTION
+The dhclient.conf file contains configuration information for
+.IR dhclient,
+the Internet Software Consortium DHCP Client.
+.PP
+The dhclient.conf file is a free-form ASCII text file. It is parsed by
+the recursive-descent parser built into dhclient. The file may contain
+extra tabs and newlines for formatting purposes. Keywords in the file
+are case-insensitive. Comments may be placed anywhere within the
+file (except within quotes). Comments begin with the # character and
+end at the end of the line.
+.PP
+The dhclient.conf file can be used to configure the behaviour of the
+client in a wide variety of ways: protocol timing, information
+requested from the server, information required of the server,
+defaults to use if the server does not provide certain information,
+values with which to override information provided by the server, or
+values to prepend or append to information provided by the server.
+The configuration file can also be preinitialized with addresses to
+use on networks that don't have DHCP servers.
+.SH PROTOCOL TIMING
+The timing behaviour of the client need not be configured by the user.
+If no timing configuration is provided by the user, a fairly
+reasonable timing behaviour will be used by default - one which
+results in fairly timely updates without placing an inordinate load on
+the server.
+.PP
+The following statements can be used to adjust the timing behaviour of
+the DHCP client if required, however:
+.PP
+.I The
+.B timeout
+.I statement
+.PP
+.B timeout
+.I time
+.B ;
+.PP
+The
+.I timeout
+statement determines the amount of time that must pass between the
+time that the client begins to try to determine its address and the
+time that it decides that it's not going to be able to contact a
+server. By default, this timeout is sixty seconds. After the
+timeout has passed, if there are any static leases defined in the
+configuration file, or any leases remaining in the lease database that
+have not yet expired, the client will loop through these leases
+attempting to validate them, and if it finds one that appears to be
+valid, it will use that lease's address. If there are no valid
+static leases or unexpired leases in the lease database, the client
+will restart the protocol after the defined retry interval.
+.PP
+.I The
+.B retry
+.I statement
+.PP
+ \fBretry \fItime\fR\fB;\fR
+.PP
+The
+.I retry
+statement determines the time that must pass after the client has
+determined that there is no DHCP server present before it tries again
+to contact a DHCP server. By default, this is five minutes.
+.PP
+.I The
+.B select-timeout
+.I statement
+.PP
+ \fBselect-timeout \fItime\fR\fB;\fR
+.PP
+It is possible (some might say desirable) for there to be more than
+one DHCP server serving any given network. In this case, it is
+possible that a client may be sent more than one offer in response to
+its initial lease discovery message. It may be that one of these
+offers is preferable to the other (e.g., one offer may have the
+address the client previously used, and the other may not).
+.PP
+The
+.I select-timeout
+is the time after the client sends its first lease discovery request
+at which it stops waiting for offers from servers, assuming that it
+has received at least one such offer. If no offers have been
+received by the time the
+.I select-timeout
+has expired, the client will accept the first offer that arrives.
+.PP
+By default, the select-timeout is zero seconds - that is, the client
+will take the first offer it sees.
+.PP
+.I The
+.B reboot
+.I statement
+.PP
+ \fBreboot \fItime\fR\fB;\fR
+.PP
+When the client is restarted, it first tries to reacquire the last
+address it had. This is called the INIT-REBOOT state. If it is
+still attached to the same network it was attached to when it last
+ran, this is the quickest way to get started. The
+.I reboot
+statement sets the time that must elapse after the client first tries
+to reacquire its old address before it gives up and tries to discover
+a new address. By default, the reboot timeout is ten seconds.
+.PP
+.I The
+.B backoff-cutoff
+.I statement
+.PP
+ \fBbackoff-cutoff \fItime\fR\fB;\fR
+.PP
+The client uses an exponential backoff algorithm with some randomness,
+so that if many clients try to configure themselves at the same time,
+they will not make their requests in lockstep. The
+.I backoff-cutoff
+statement determines the maximum amount of time that the client is
+allowed to back off. It defaults to two minutes.
+.PP
+.I The
+.B initial-interval
+.I statement
+.PP
+ \fBinitial-interval \fItime\fR\fB;\fR
+.PP
+The
+.I initial-interval
+statement sets the amount of time between the first attempt to reach a
+server and the second attempt to reach a server. Each time a message
+is sent, the interval between messages is incremented by twice the
+current interval multiplied by a random number between zero and one.
+If it is greater than the backoff-cutoff amount, it is set to that
+amount. It defaults to ten seconds.
+.SH LEASE REQUIREMENTS AND REQUESTS
+The DHCP protocol allows the client to request that the server send it
+specific information, and not send it other information that it is not
+prepared to accept. The protocol also allows the client to reject
+offers from servers if they don't contain information the client
+needs, or if the information provided is not satisfactory.
+.PP
+There is a variety of data contained in offers that DHCP servers send
+to DHCP clients. The data that can be specifically requested is what
+are called \fIDHCP Options\fR. DHCP Options are defined in
+ \fBdhcp-options(5)\fR.
+.PP
+.I The
+.B request
+.I statement
+.PP
+ \fBrequest [ \fIoption\fR ] [\fB,\fI ... \fIoption\fR ]\fB;\fR
+.PP
+The request statement causes the client to request that any server
+responding to the client send the client its values for the specified
+options. Only the option names should be specified in the request
+statement - not option parameters.
+.PP
+.I The
+.B require
+.I statement
+.PP
+ \fBrequire [ \fIoption\fR ] [\fB,\fI ... \fIoption ]\fB;\fR
+.PP
+The require statement lists options that must be sent in order for an
+offer to be accepted. Offers that do not contain all the listed
+options will be ignored.
+.PP
+.I The
+.B send
+.I statement
+.PP
+ \fBsend { [ \fIoption declaration\fR ]
+[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+.PP
+The send statement causes the client to send the specified options to
+the server with the specified values. These are full option
+declarations as described in \fBdhcp-options(5)\fR. Options that are
+always sent in the DHCP protocol should not be specified here, except
+that the client can specify a \fBrequested-lease-time\fR option other
+than the default requested lease time, which is two hours. The other
+obvious use for this statement is to send information to the server
+that will allow it to differentiate between this client and other
+clients or kinds of clients.
+.SH OPTION MODIFIERS
+In some cases, a client may receive option data from the server which
+is not really appropriate for that client, or may not receive
+information that it needs, and for which a useful default value
+exists. It may also receive information which is useful, but which
+needs to be supplemented with local information. To handle these
+needs, several option modifiers are available.
+.PP
+.I The
+.B default
+.I statement
+.PP
+ \fBdefault { [ \fIoption declaration\fR ]
+[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+.PP
+If for some set of options the client should use the value supplied by
+the server, but needs to use some default value if no value was supplied
+by the server, these values can be defined in the
+.B default
+statement.
+.PP
+.I The
+.B supersede
+.I statement
+.PP
+ \fBsupersede { [ \fIoption declaration\fR ]
+[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+.PP
+If for some set of options the client should always use its own value
+rather than any value supplied by the server, these values can be
+defined in the
+.B supersede
+statement.
+.PP
+.I The
+.B prepend
+.I statement
+.PP
+ \fBprepend { [ \fIoption declaration\fR ]
+[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+.PP
+If for some set of options the client should first a value it
+supplies, and then use the values supplied by
+the server, if any, these values can be defined in the
+.B prepend
+statement. The
+.B prepend
+statement can only be used for options which
+allow more than one value to be given.
+.PP
+.I The
+.B append
+.I statement
+.PP
+ \fBappend { [ \fIoption declaration\fR ]
+[\fB,\fI ... \fIoption declaration\fR ]\fB}\fR
+.PP
+If for some set of options the client should first a value it
+supplies, and then use the values supplied by
+the server, if any, these values can be defined in the
+.B append
+statement. The
+.B append
+statement can only be used for options which
+allow more than one value to be given.
+.SH LEASE DECLARATIONS
+.PP
+.I The
+.B lease
+.I declaration
+.PP
+ \fBlease {\fR \fIlease-declaration\fR [ ... \fIlease-declaration ] \fB}\fR
+.PP
+The DHCP client may decide after some period of time (see \fBPROTOCOL
+TIMING\fR) decide that it is not going to succeed in contacting a
+server. At that time, it consults its own database of old leases and
+tests each one that has not yet timed out by pinging the listed router
+for that lease to see if that lease could work. It is possible to
+define one or more \fIfixed\fR leases in the client configuration file
+for networks where there is no DHCP or BOOTP service, so that the
+client can still automatically configure its address. This is done
+with the
+.B lease
+statement.
+.PP
+NOTE: the lease statement is also used in the dhclient.leases file in
+order to record leases that have been received from DHCP servers.
+Some of the syntax for leases as described below is only needed in the
+dhclient.leases file. Such syntax is documented here for
+completeness.
+.PP
+A lease statement consists of the lease keyword, followed by a left
+curly brace, followed by one or more lease declaration statements,
+followed by a right curly brace. The following lease declarations
+are possible:
+.PP
+ \fBbootp;\fR
+.PP
+The
+.B bootp
+statement is used to indicate that the lease was acquired using the
+BOOTP protocol rather than the DHCP protocol. It is never necessary
+to specify this in the client configuration file. The client uses
+this syntax in its lease database file.
+.PP
+ \fBinterface\fR \fB"\fR\fIstring\fR\fB";\fR
+.PP
+The
+.B interface
+lease statement is used to indicate the interface on which the lease
+is valid. If set, this lease will only be tried on a particular
+interface. When the client receives a lease from a server, it always
+records the interface number on which it received that lease.
+If predefined leases are specified in the dhclient.conf file, the
+interface should also be specified, although this is not required.
+.PP
+ \fBfixed-address\fR \fIip-address\fR\fB;\fR
+.PP
+The
+.B fixed-address
+statement is used to set the ip address of a particular lease. This
+is required for all lease statements. The IP address must be
+specified as a dotted quad (e.g., 12.34.56.78).
+.PP
+ \fBfilename "\fR\fIstring\fR\fB";\fR
+.PP
+The
+.B filename
+statement specifies the name of the boot filename to use. This is
+not used by the standard client configuration script, but is included
+for completeness.
+.PP
+ \fBserver-name "\fR\fIstring\fR\fB";\fR
+.PP
+The
+.B server-name
+statement specifies the name of the boot server name to use. This is
+also not used by the standard client configuration script.
+.PP
+ \fBoption\fR \fIoption-declaration\fR\fB;\fR
+.PP
+The
+.B option
+statement is used to specify the value of an option supplied by the
+server, or, in the case of predefined leases declared in
+dhclient.conf, the value that the user wishes the client configuration
+script to use if the predefined lease is used.
+.PP
+ \fBscript "\fIscript-name\fB";\fR
+.PP
+The
+.B script
+statement is used to specify the pathname of the dhcp client
+configuration script. This script is used by the dhcp client to set
+each interface's initial configuration prior to requesting an address,
+to test the address once it has been offered, and to set the
+interface's final configuration once a lease has been acquired. If
+no lease is acquired, the script is used to test predefined leases, if
+any, and also called once if no valid lease can be identified. For
+more information, see
+.B dhclient-lease(8).
+.PP
+ \fBmedium "\fImedia setup\fB";\fR
+.PP
+The
+.B medium
+statement can be used on systems where network interfaces cannot
+automatically determine the type of network to which they are
+connected. The media setup string is a system-dependent parameter
+which is passed to the dhcp client configuration script when
+initializing the interface. On Unix and Unix-like systems, the
+argument is passed on the ifconfig command line when configuring te
+interface.
+.PP
+The dhcp client automatically declares this parameter if it used a
+media type (see the
+.B media
+statement) when configuring the interface in order to obtain a lease.
+This statement should be used in predefined leases only if the network
+interface requires media type configuration.
+.PP
+ \fBrenew\fR \fIdate\fB;\fR
+.PP
+ \fBrebind\fR \fIdate\fB;\fR
+.PP
+ \fBexpire\fR \fIdate\fB;\fR
+.PP
+The \fBrenew\fR statement defines the time at which the dhcp client
+should begin trying to contact its server to renew a lease that it is
+using. The \fBrebind\fR statement defines the time at which the dhcp
+client should begin to try to contact \fIany\fR dhcp server in order
+to renew its lease. The \fBexpire\fR statement defines the time at
+which the dhcp client must stop using a lease if it has not been able
+to contact a server in order to renew it.
+.PP
+These declarations are automatically set in leases acquired by the
+DHCP client, but must also be configured in predefined leases - a
+predefined lease whose expiry time has passed will not be used by the
+DHCP client.
+.PP
+Dates are specified as follows:
+.PP
+ \fI<weekday> <year>\fB/\fI<month>\fB/\fI<day>
+<hour>\fB:\fI<minute>\fB:\fI<second>\fR
+.PP
+The weekday is present to make it easy for a human to tell when a
+lease expires - it's specified as a number from zero to six, with zero
+being Sunday. When declaring a predefined lease, it can always be
+specified as zero. The year is specified with the century, so it
+should generally be four digits except for really long leases. The
+month is specified as a number starting with 1 for January. The day
+of the month is likewise specified starting with 1. The hour is a
+number between 0 and 23, the minute a number between 0 and 69, and the
+second also a number between 0 and 69.
+.SH ALIAS DECLARATIONS
+ \fBalias { \fI declarations ... \fB}\fR
+.PP
+Some DHCP clients running TCP/IP roaming protocols may require that in
+addition to the lease they may acquire via DHCP, their interface also
+be configured with a predefined IP alias so that they can have a
+permanent IP address even while roaming. The Internet Software
+Consortium DHCP client doesn't support roaming with fixed addresses
+directly, but in order to facilitate such experimentation, the dhcp
+client can be set up to configure an IP alias using the
+.B alias
+declaration.
+.PP
+The alias declaration resembles a lease declaration, except that
+options other than the subnet-mask option are ignored by the standard
+client configuration script, and expiry times are ignored. A typical
+alias declaration includes an interface declaration, a fixed-address
+declaration for the IP alias address, and a subnet-mask option
+declaration. A medium statement should never be included in an alias
+declaration.
+.SH OTHER DECLARATIONS
+ \fBreject \fIip-address\fB;\fR
+.PP
+The reject statement causes the DHCP client to reject offers from
+servers who use the specified address as a server identifier. This
+can be used to avoid being configured by rogue or misconfigured dhcp
+servers, although it should be a last resort - better to track down
+the bad DHCP server and fix it.
+.PP
+ \fBinterface "\fIname\fB" { \fIdeclarations ... \fB }
+.PP
+A client with more than one network interface may require different
+behaviour depending on which interface is being configured. All
+timing parameters and declarations other than lease and alias
+declarations can be enclosed in an interface declaration, and those
+parameters will then be used only for the interface that matches the
+specified name. Interfaces for which there is no interface
+declaration will use the parameters declared outside of any interface
+declaration, or the default settings.
+.PP
+ \fBmedia "\fImedia setup\fB"\fI [ \fB, "\fImedia setup\fB", \fI... ]\fB;\fR
+.PP
+The
+.B media
+statement defines one or more media configuration parameters which may
+be tried while attempting to acquire an IP address. The dhcp client
+will cycle through each media setup string on the list, configuring
+the interface using that setup and attempting to boot, and then trying
+the next one. This can be used for network interfaces which aren't
+capable of sensing the media type unaided - whichever media type
+succeeds in getting a request to the server and hearing the reply is
+probably right (no guarantees).
+.PP
+The media setup is only used for the initial phase of address
+acquisition (the DHCPDISCOVER and DHCPOFFER packtes). Once an
+address has been acquired, the dhcp client will record it in its lease
+database and will record the media type used to acquire the address.
+Whenever the client tries to renew the lease, it will use that same
+media type. The lease must expire before the client will go back to
+cycling through media types.
+.SH SAMPLE
+The following configuration file is used on a laptop running NetBSD
+1.3. The laptop has an IP alias of 192.5.5.213, and has one
+interface, ep0 (a 3com 3C589C). Booting intervals have been
+shortened somewhat from the default, because the client is known to
+spend most of its time on networks with little DHCP activity. The
+laptop does roam to multiple networks.
+
+.nf
+
+timeout 60;
+retry 60;
+reboot 10;
+select-timeout 5;
+initial-interval 2;
+reject 192.33.137.209;
+
+interface "ep0" {
+ send host-name "andare.fugue.com";
+ send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
+ send dhcp-lease-time 3600;
+ supersede domain-name "fugue.com rc.vix.com home.vix.com";
+ prepend domain-name-servers 127.0.0.1;
+ request subnet-mask, broadcast-address, time-offset, routers,
+ domain-name, domain-name-servers, host-name;
+ require subnet-mask, domain-name-servers;
+ script "/etc/dhclient-script";
+ media "media 10baseT/UTP", "media 10base2/BNC";
+}
+
+alias {
+ interface "ep0";
+ fixed-address 192.5.5.213;
+ option subnet-mask 255.255.255.255;
+}
+.fi
+This is a very complicated dhclient.conf file - in general, yours
+should be much simpler. In many cases, it's sufficient to just
+create an empty dhclient.conf file - the defaults are usually fine.
+.SH SEE ALSO
+dhcp-options(5), dhclient.leases(5), dhcpd(8), dhcpd.conf(5), RFC2132,
+RFC2131.
+.SH AUTHOR
+.B dhclient(8)
+was written by Ted Lemon <mellon@vix.com>
+under a contract with Vixie Labs. Funding
+for this project was provided by the Internet Software Corporation.
+Information about the Internet Software Consortium can be found at
+.B http://www.isc.org/isc.
diff --git a/contrib/isc-dhcp/client/dhclient.leases.5 b/contrib/isc-dhcp/client/dhclient.leases.5
new file mode 100644
index 000000000000..e0da360524a8
--- /dev/null
+++ b/contrib/isc-dhcp/client/dhclient.leases.5
@@ -0,0 +1,62 @@
+.\" dhclient.conf.5
+.\"
+.\" Copyright (c) 1997 The Internet Software Consortium.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of The Internet Software Consortium nor the names
+.\" of its contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" This software has been written for the Internet Software Consortium
+.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+.\" Enterprises. To learn more about the Internet Software Consortium,
+.\" see ``http://www.isc.org/isc''. To learn more about Vixie
+.\" Enterprises, see ``http://www.vix.com''.
+.TH dhclient.leases 5
+.SH NAME
+dhclient.leases - DHCP client lease database
+.SH DESCRIPTION
+The Internet Software Consortium DHCP client keeps a persistent
+database of leases that it has acquired that are still valid. The
+database is a free-form ASCII file containing one valid declaration
+per lease. If more than one declaration appears for a given lease,
+the last one in the file is used. The file is written as a log, so
+this is not an unusual occurrance.
+.PP
+The format of the lease declarations is described in
+.B dhclient.conf(5).
+.SH FILES
+.B DBDIR/dhclient.leases
+.SH SEE ALSO
+dhclient(8), dhcp-options(5), dhclient.conf(5), dhcpd(8),
+dhcpd.conf(5), RFC2132, RFC2131.
+.SH AUTHOR
+.B dhclient(8)
+was written by Ted Lemon <mellon@vix.com>
+under a contract with Vixie Labs. Funding
+for this project was provided by the Internet Software Corporation.
+Information about the Internet Software Consortium can be found at
+.B http://www.isc.org/isc.
diff --git a/contrib/isc-dhcp/client/scripts/freebsd b/contrib/isc-dhcp/client/scripts/freebsd
new file mode 100755
index 000000000000..7236a67a9a9a
--- /dev/null
+++ b/contrib/isc-dhcp/client/scripts/freebsd
@@ -0,0 +1,174 @@
+#!/bin/sh
+
+if [ x$new_network_number != x ]; then
+ echo New Network Number: $new_network_number
+fi
+
+if [ x$new_broadcast_address != x ]; then
+ echo New Broadcast Address: $new_broadcast_address
+ new_broadcast_arg="broadcast $new_broadcast_address"
+fi
+if [ x$old_broadcast_address != x ]; then
+ old_broadcast_arg="broadcast $old_broadcast_address"
+fi
+if [ x$new_subnet_mask != x ]; then
+ new_netmask_arg="netmask $new_subnet_mask"
+fi
+if [ x$old_subnet_mask != x ]; then
+ old_netmask_arg="netmask $old_subnet_mask"
+fi
+if [ x$alias_subnet_mask != x ]; then
+ alias_subnet_arg="netmask $alias_subnet_mask"
+fi
+
+if [ x$reason = xMEDIUM ]; then
+ ifconfig $interface $medium
+ ifconfig $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1
+ sleep 1
+ exit 0
+fi
+
+if [ x$reason = xPREINIT ]; then
+ if [ x$alias_ip_address != x ]; then
+ ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
+ route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
+ fi
+ ifconfig $interface inet 0.0.0.0 netmask 0.0.0.0 \
+ broadcast 255.255.255.255 up
+ exit 0
+fi
+
+if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then
+ exit 0;
+fi
+
+if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \
+ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then
+ if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \
+ [ x$alias_ip_address != x$old_ip_address ]; then
+ ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
+ route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
+ fi
+ if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then
+ ifconfig $interface inet -alias $old_ip_address $medium
+ route delete $old_ip_address 127.1 >/dev/null 2>&1
+ for router in $old_routers; do
+ route delete default $router >/dev/null 2>&1
+ done
+ if [ "$old_static_routes" != "" ]; then
+ set $old_static_routes
+ while [ $# -gt 1 ]; do
+ route delete $1 $2
+ shift; shift
+ done
+ fi
+ arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' |sh
+ fi
+ if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \
+ [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then
+ ifconfig $interface inet $new_ip_address $new_netmask_arg \
+ $new_broadcast_arg $medium
+ route add $new_ip_address 127.1 >/dev/null 2>&1
+ for router in $new_routers; do
+ route add default $router >/dev/null 2>&1
+ done
+ if [ "$new_static_routes" != "" ]; then
+ set $new_static_routes
+ while [ $# -gt 1 ]; do
+ route add $1 $2
+ shift; shift
+ done
+ fi
+ fi
+ if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ];
+ then
+ ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
+ route add $alias_ip_address 127.0.0.1
+ fi
+ echo search $new_domain_name >/etc/resolv.conf
+ for nameserver in $new_domain_name_servers; do
+ echo nameserver $nameserver >>/etc/resolv.conf
+ done
+ exit 0
+fi
+
+if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ]; then
+ if [ x$alias_ip_address != x ]; then
+ ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
+ route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
+ fi
+ if [ x$old_ip_address != x ]; then
+ ifconfig $interface inet -alias $old_ip_address $medium
+ route delete $old_ip_address 127.1 >/dev/null 2>&1
+ for router in $old_routers; do
+ route delete default $router >/dev/null 2>&1
+ done
+ if [ "$old_static_routes" != "" ]; then
+ set $old_static_routes
+ while [ $# -gt 1 ]; do
+ route delete $1 $2
+ shift; shift
+ done
+ fi
+ arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
+ |sh >/dev/null 2>&1
+ fi
+ if [ x$alias_ip_address != x ]; then
+ ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
+ route add $alias_ip_address 127.0.0.1
+ fi
+ exit 0
+fi
+
+if [ x$reason = xTIMEOUT ]; then
+ if [ x$alias_ip_address != x ]; then
+ ifconfig $interface inet -alias $alias_ip_address > /dev/null 2>&1
+ route delete $alias_ip_address 127.0.0.1 > /dev/null 2>&1
+ fi
+ ifconfig $interface inet $new_ip_address $new_netmask_arg \
+ $new_broadcast_arg $medium
+ sleep 1
+ if [ "$new_routers" != "" ]; then
+ set $new_routers
+ if ping -q -c 1 -w 1 $1; then
+ if [ x$new_ip_address != x$alias_ip_address ] && \
+ [ x$alias_ip_address != x ]; then
+ ifconfig $interface inet alias $alias_ip_address $alias_subnet_arg
+ route add $alias_ip_address 127.0.0.1
+ fi
+ route add $new_ip_address 127.1 >/dev/null 2>&1
+ for router in $new_routers; do
+ route add default $router >/dev/null 2>&1
+ done
+ set $new_static_routes
+ while [ $# -gt 1 ]; do
+ route add $0 $1
+ shift; shift
+ done
+ echo search $new_domain_name >/etc/resolv.conf.std
+ for nameserver in $new_domain_name_servers; do
+ echo nameserver $nameserver >>/etc/resolv.conf.std
+ done
+ if [ -f /etc/resolv.conf ]; then
+ rm -f /etc/resolv.conf
+ fi
+ mv /etc/resolv.conf.std /etc/resolv.conf
+ exit 0
+ fi
+ ifconfig $interface inet -alias $new_ip_address $medium
+ for router in $old_routers; do
+ route delete default $router >/dev/null 2>&1
+ done
+ if [ "$old_static_routes" != "" ]; then
+ set $old_static_routes
+ while [ $# -gt 1 ]; do
+ route delete $1 $2
+ shift; shift
+ done
+ fi
+ arp -n -a | sed -n -e 's/^.*(\(.*\)) at .*$/arp -n -d \1/p' \
+ |sh >/dev/null 2>&1
+ exit 1
+fi
+
+exit 0
diff --git a/contrib/isc-dhcp/common/alloc.c b/contrib/isc-dhcp/common/alloc.c
new file mode 100644
index 000000000000..172fcea606dd
--- /dev/null
+++ b/contrib/isc-dhcp/common/alloc.c
@@ -0,0 +1,329 @@
+/* alloc.c
+
+ Memory allocation... */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: alloc.c,v 1.13 1997/05/09 07:56:13 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+struct dhcp_packet *dhcp_free_list;
+struct packet *packet_free_list;
+
+VOIDPTR dmalloc (size, name)
+ int size;
+ char *name;
+{
+ VOIDPTR foo = (VOIDPTR)malloc (size);
+ if (!foo)
+ warn ("No memory for %s.", name);
+ memset (foo, 0, size);
+ return foo;
+}
+
+void dfree (ptr, name)
+ VOIDPTR ptr;
+ char *name;
+{
+ if (!ptr) {
+ warn ("dfree %s: free on null pointer.", name);
+ return;
+ }
+ free (ptr);
+}
+
+struct packet *new_packet (name)
+ char *name;
+{
+ struct packet *rval;
+ rval = (struct packet *)dmalloc (sizeof (struct packet), name);
+ return rval;
+}
+
+struct dhcp_packet *new_dhcp_packet (name)
+ char *name;
+{
+ struct dhcp_packet *rval;
+ rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
+ name);
+ return rval;
+}
+
+struct tree *new_tree (name)
+ char *name;
+{
+ struct tree *rval = dmalloc (sizeof (struct tree), name);
+ return rval;
+}
+
+struct tree_cache *free_tree_caches;
+
+struct tree_cache *new_tree_cache (name)
+ char *name;
+{
+ struct tree_cache *rval;
+
+ if (free_tree_caches) {
+ rval = free_tree_caches;
+ free_tree_caches =
+ (struct tree_cache *)(rval -> value);
+ } else {
+ rval = dmalloc (sizeof (struct tree_cache), name);
+ if (!rval)
+ error ("unable to allocate tree cache for %s.", name);
+ }
+ return rval;
+}
+
+struct hash_table *new_hash_table (count, name)
+ int count;
+ char *name;
+{
+ struct hash_table *rval = dmalloc (sizeof (struct hash_table)
+ - (DEFAULT_HASH_SIZE
+ * sizeof (struct hash_bucket *))
+ + (count
+ * sizeof (struct hash_bucket *)),
+ name);
+ rval -> hash_count = count;
+ return rval;
+}
+
+struct hash_bucket *new_hash_bucket (name)
+ char *name;
+{
+ struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket), name);
+ return rval;
+}
+
+struct lease *new_leases (n, name)
+ int n;
+ char *name;
+{
+ struct lease *rval = dmalloc (n * sizeof (struct lease), name);
+ return rval;
+}
+
+struct lease *new_lease (name)
+ char *name;
+{
+ struct lease *rval = dmalloc (sizeof (struct lease), name);
+ return rval;
+}
+
+struct subnet *new_subnet (name)
+ char *name;
+{
+ struct subnet *rval = dmalloc (sizeof (struct subnet), name);
+ return rval;
+}
+
+struct class *new_class (name)
+ char *name;
+{
+ struct class *rval = dmalloc (sizeof (struct class), name);
+ return rval;
+}
+
+struct shared_network *new_shared_network (name)
+ char *name;
+{
+ struct shared_network *rval =
+ dmalloc (sizeof (struct shared_network), name);
+ return rval;
+}
+
+struct group *new_group (name)
+ char *name;
+{
+ struct group *rval =
+ dmalloc (sizeof (struct group), name);
+ return rval;
+}
+
+struct protocol *new_protocol (name)
+ char *name;
+{
+ struct protocol *rval = dmalloc (sizeof (struct protocol), name);
+ return rval;
+}
+
+struct lease_state *free_lease_states;
+
+struct lease_state *new_lease_state (name)
+ char *name;
+{
+ struct lease_state *rval;
+
+ if (free_lease_states) {
+ rval = free_lease_states;
+ free_lease_states =
+ (struct lease_state *)(free_lease_states -> next);
+ } else {
+ rval = dmalloc (sizeof (struct lease_state), name);
+ }
+ return rval;
+}
+
+struct domain_search_list *new_domain_search_list (name)
+ char *name;
+{
+ struct domain_search_list *rval =
+ dmalloc (sizeof (struct domain_search_list), name);
+ return rval;
+}
+
+struct name_server *new_name_server (name)
+ char *name;
+{
+ struct name_server *rval =
+ dmalloc (sizeof (struct name_server), name);
+ return rval;
+}
+
+void free_name_server (ptr, name)
+ struct name_server *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_domain_search_list (ptr, name)
+ struct domain_search_list *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_lease_state (ptr, name)
+ struct lease_state *ptr;
+ char *name;
+{
+ ptr -> next = free_lease_states;
+ free_lease_states = ptr;
+}
+
+void free_protocol (ptr, name)
+ struct protocol *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_group (ptr, name)
+ struct group *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_shared_network (ptr, name)
+ struct shared_network *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_class (ptr, name)
+ struct class *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_subnet (ptr, name)
+ struct subnet *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_lease (ptr, name)
+ struct lease *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_hash_bucket (ptr, name)
+ struct hash_bucket *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_hash_table (ptr, name)
+ struct hash_table *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_tree_cache (ptr, name)
+ struct tree_cache *ptr;
+ char *name;
+{
+ ptr -> value = (unsigned char *)free_tree_caches;
+ free_tree_caches = ptr;
+}
+
+void free_packet (ptr, name)
+ struct packet *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_dhcp_packet (ptr, name)
+ struct dhcp_packet *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
+
+void free_tree (ptr, name)
+ struct tree *ptr;
+ char *name;
+{
+ dfree ((VOIDPTR)ptr, name);
+}
diff --git a/contrib/isc-dhcp/common/bpf.c b/contrib/isc-dhcp/common/bpf.c
new file mode 100644
index 000000000000..e47aa1f7822c
--- /dev/null
+++ b/contrib/isc-dhcp/common/bpf.c
@@ -0,0 +1,386 @@
+/* bpf.c
+
+ BPF socket interface code, originally contributed by Archie Cobbs. */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: bpf.c,v 1.19 1997/10/20 21:47:13 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <net/bpf.h>
+#ifdef NEED_OSF_PFILT_HACKS
+#include <net/pfilt.h>
+#endif
+#include <netinet/in_systm.h>
+#include "includes/netinet/ip.h"
+#include "includes/netinet/udp.h"
+#include "includes/netinet/if_ether.h"
+
+/* Reinitializes the specified interface after an address change. This
+ is not required for packet-filter APIs. */
+
+#ifdef USE_BPF_SEND
+void if_reinitialize_send (info)
+ struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_BPF_RECEIVE
+void if_reinitialize_receive (info)
+ struct interface_info *info;
+{
+}
+#endif
+
+/* Called by get_interface_list for each interface that's discovered.
+ Opens a packet filter for each interface and adds it to the select
+ mask. */
+
+int if_register_bpf (info)
+ struct interface_info *info;
+{
+ int sock;
+ char filename[50];
+ int b;
+
+ /* Open a BPF device */
+ for (b = 0; 1; b++) {
+#ifndef NO_SNPRINTF
+ snprintf(filename, sizeof(filename), BPF_FORMAT, b);
+#else
+ sprintf(filename, BPF_FORMAT, b);
+#endif
+ sock = open (filename, O_RDWR, 0);
+ if (sock < 0) {
+ if (errno == EBUSY) {
+ continue;
+ } else {
+ error ("Can't find free bpf: %m");
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* Set the BPF device to point at this interface. */
+ if (ioctl (sock, BIOCSETIF, info -> ifp) < 0)
+ error ("Can't attach interface %s to bpf device %s: %m",
+ info -> name, filename);
+
+ return sock;
+}
+#endif /* USE_BPF_SEND || USE_BPF_RECEIVE */
+
+#ifdef USE_BPF_SEND
+void if_register_send (info)
+ struct interface_info *info;
+{
+ /* If we're using the bpf API for sending and receiving,
+ we don't need to register this interface twice. */
+#ifndef USE_BPF_RECEIVE
+ info -> wfdesc = if_register_bpf (info, interface);
+#else
+ info -> wfdesc = info -> rfdesc;
+#endif
+ if (!quiet_interface_discovery)
+ note ("Sending on BPF/%s/%s/%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_BPF_SEND */
+
+#ifdef USE_BPF_RECEIVE
+/* Packet filter program...
+ XXX Changes to the filter program may require changes to the constant
+ offsets used in if_register_send to patch the BPF program! XXX */
+
+struct bpf_insn filter [] = {
+ /* Make sure this is an IP packet... */
+ BPF_STMT (BPF_LD + BPF_H + BPF_ABS, 12),
+ BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
+
+ /* Make sure it's a UDP packet... */
+ BPF_STMT (BPF_LD + BPF_B + BPF_ABS, 23),
+ BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
+
+ /* Make sure this isn't a fragment... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
+ BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
+
+ /* Get the IP header length... */
+ BPF_STMT (BPF_LDX + BPF_B + BPF_MSH, 14),
+
+ /* Make sure it's to the right port... */
+ BPF_STMT (BPF_LD + BPF_H + BPF_IND, 16),
+ BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
+void if_register_receive (info)
+ struct interface_info *info;
+{
+ int flag = 1;
+ struct bpf_version v;
+ u_int32_t addr;
+ struct bpf_program p;
+ u_int32_t bits;
+
+ /* Open a BPF device and hang it on this interface... */
+ info -> rfdesc = if_register_bpf (info);
+
+ /* Make sure the BPF version is in range... */
+ if (ioctl (info -> rfdesc, BIOCVERSION, &v) < 0)
+ error ("Can't get BPF version: %m");
+
+ if (v.bv_major != BPF_MAJOR_VERSION ||
+ v.bv_minor < BPF_MINOR_VERSION)
+ error ("Kernel BPF version out of range - recompile dhcpd!");
+
+ /* Set immediate mode so that reads return as soon as a packet
+ comes in, rather than waiting for the input buffer to fill with
+ packets. */
+ if (ioctl (info -> rfdesc, BIOCIMMEDIATE, &flag) < 0)
+ error ("Can't set immediate mode on bpf device: %m");
+
+#ifdef NEED_OSF_PFILT_HACKS
+ /* Allow the copyall flag to be set... */
+ if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
+ error ("Can't set ALLOWCOPYALL: %m");
+
+ /* Clear all the packet filter mode bits first... */
+ bits = 0;
+ if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
+ error ("Can't clear pfilt bits: %m");
+
+ /* Set the ENBATCH, ENCOPYALL, ENBPFHDR bits... */
+ bits = ENBATCH | ENCOPYALL | ENBPFHDR;
+ if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
+ error ("Can't set ENBATCH|ENCOPYALL|ENBPFHDR: %m");
+#endif
+ /* Get the required BPF buffer length from the kernel. */
+ if (ioctl (info -> rfdesc, BIOCGBLEN, &info -> rbuf_max) < 0)
+ error ("Can't get bpf buffer length: %m");
+ info -> rbuf = malloc (info -> rbuf_max);
+ if (!info -> rbuf)
+ error ("Can't allocate %d bytes for bpf input buffer.");
+ info -> rbuf_offset = 0;
+ info -> rbuf_len = 0;
+
+ /* Set up the bpf filter program structure. */
+ p.bf_len = sizeof filter / sizeof (struct bpf_insn);
+ p.bf_insns = filter;
+
+ /* Patch the server port into the BPF program...
+ XXX changes to filter program may require changes
+ to the insn number(s) used below! XXX */
+ filter [8].k = ntohs (local_port);
+
+ if (ioctl (info -> rfdesc, BIOCSETF, &p) < 0)
+ error ("Can't install packet filter program: %m");
+ if (!quiet_interface_discovery)
+ note ("Listening on BPF/%s/%s/%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_BPF_RECEIVE */
+
+#ifdef USE_BPF_SEND
+ssize_t send_packet (interface, packet, raw, len, from, to, hto)
+ struct interface_info *interface;
+ struct packet *packet;
+ struct dhcp_packet *raw;
+ size_t len;
+ struct in_addr from;
+ struct sockaddr_in *to;
+ struct hardware *hto;
+{
+ int bufp = 0;
+ unsigned char buf [256];
+ struct iovec iov [2];
+
+ /* Assemble the headers... */
+ assemble_hw_header (interface, buf, &bufp, hto);
+ assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
+ to -> sin_addr.s_addr, to -> sin_port,
+ (unsigned char *)raw, len);
+
+ /* Fire it off */
+ iov [0].iov_base = (char *)buf;
+ iov [0].iov_len = bufp;
+ iov [1].iov_base = (char *)raw;
+ iov [1].iov_len = len;
+
+ return writev(interface -> wfdesc, iov, 2);
+}
+#endif /* USE_BPF_SEND */
+
+#ifdef USE_BPF_RECEIVE
+ssize_t receive_packet (interface, buf, len, from, hfrom)
+ struct interface_info *interface;
+ unsigned char *buf;
+ size_t len;
+ struct sockaddr_in *from;
+ struct hardware *hfrom;
+{
+ int length = 0;
+ int offset = 0;
+ struct bpf_hdr hdr;
+
+ /* All this complexity is because BPF doesn't guarantee
+ that only one packet will be returned at a time. We're
+ getting what we deserve, though - this is a terrible abuse
+ of the BPF interface. Sigh. */
+
+ /* Process packets until we get one we can return or until we've
+ done a read and gotten nothing we can return... */
+
+ do {
+ /* If the buffer is empty, fill it. */
+ if (interface -> rbuf_offset == interface -> rbuf_len) {
+ length = read (interface -> rfdesc,
+ interface -> rbuf,
+ interface -> rbuf_max);
+ if (length <= 0)
+ return length;
+ interface -> rbuf_offset = 0;
+ interface -> rbuf_len = length;
+ }
+
+ /* If there isn't room for a whole bpf header, something went
+ wrong, but we'll ignore it and hope it goes away... XXX */
+ if (interface -> rbuf_len -
+ interface -> rbuf_offset < sizeof hdr) {
+ interface -> rbuf_offset = interface -> rbuf_len;
+ continue;
+ }
+
+ /* Copy out a bpf header... */
+ memcpy (&hdr, &interface -> rbuf [interface -> rbuf_offset],
+ sizeof hdr);
+
+ /* If the bpf header plus data doesn't fit in what's left
+ of the buffer, stick head in sand yet again... */
+ if (interface -> rbuf_offset +
+ hdr.bh_hdrlen + hdr.bh_caplen > interface -> rbuf_len) {
+ interface -> rbuf_offset = interface -> rbuf_len;
+ continue;
+ }
+
+ /* If the captured data wasn't the whole packet, or if
+ the packet won't fit in the input buffer, all we
+ can do is drop it. */
+ if (hdr.bh_caplen != hdr.bh_datalen) {
+ interface -> rbuf_offset +=
+ hdr.bh_hdrlen = hdr.bh_caplen;
+ continue;
+ }
+
+ /* Skip over the BPF header... */
+ interface -> rbuf_offset += hdr.bh_hdrlen;
+
+ /* Decode the physical header... */
+ offset = decode_hw_header (interface,
+ interface -> rbuf,
+ interface -> rbuf_offset,
+ hfrom);
+
+ /* If a physical layer checksum failed (dunno of any
+ physical layer that supports this, but WTH), skip this
+ packet. */
+ if (offset < 0) {
+ interface -> rbuf_offset += hdr.bh_caplen;
+ continue;
+ }
+ interface -> rbuf_offset += offset;
+ hdr.bh_caplen -= offset;
+
+ /* Decode the IP and UDP headers... */
+ offset = decode_udp_ip_header (interface,
+ interface -> rbuf,
+ interface -> rbuf_offset,
+ from,
+ (unsigned char *)0,
+ hdr.bh_caplen);
+
+ /* If the IP or UDP checksum was bad, skip the packet... */
+ if (offset < 0) {
+ interface -> rbuf_offset += hdr.bh_caplen;
+ continue;
+ }
+ interface -> rbuf_offset += offset;
+ hdr.bh_caplen -= offset;
+
+ /* If there's not enough room to stash the packet data,
+ we have to skip it (this shouldn't happen in real
+ life, though). */
+ if (hdr.bh_caplen > len) {
+ interface -> rbuf_offset += hdr.bh_caplen;
+ continue;
+ }
+
+ /* Copy out the data in the packet... */
+ memcpy (buf, interface -> rbuf + interface -> rbuf_offset,
+ hdr.bh_caplen);
+ interface -> rbuf_offset += hdr.bh_caplen;
+ return hdr.bh_caplen;
+ } while (!length);
+ return 0;
+}
+#endif
diff --git a/contrib/isc-dhcp/common/conflex.c b/contrib/isc-dhcp/common/conflex.c
new file mode 100644
index 000000000000..eedfa054b662
--- /dev/null
+++ b/contrib/isc-dhcp/common/conflex.c
@@ -0,0 +1,548 @@
+/* conflex.c
+
+ Lexical scanner for dhcpd config file... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: conflex.c,v 1.29 1997/10/29 18:32:53 mellon Exp $ Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+#include <ctype.h>
+
+int lexline;
+int lexchar;
+char *token_line;
+char *prev_line;
+char *cur_line;
+char *tlname;
+int eol_token;
+
+static char line1 [81];
+static char line2 [81];
+static int lpos;
+static int line;
+static int tlpos;
+static int tline;
+static int token;
+static int ugflag;
+static char *tval;
+static char tokbuf [1500];
+
+#ifdef OLD_LEXER
+char comments [4096];
+int comment_index;
+#endif
+
+
+static int get_char PROTO ((FILE *));
+static int get_token PROTO ((FILE *));
+static void skip_to_eol PROTO ((FILE *));
+static int read_string PROTO ((FILE *));
+static int read_number PROTO ((int, FILE *));
+static int read_num_or_name PROTO ((int, FILE *));
+static int intern PROTO ((char *, int));
+
+void new_parse (name)
+ char *name;
+{
+ tlname = name;
+ lpos = line = 1;
+ cur_line = line1;
+ prev_line = line2;
+ token_line = cur_line;
+ cur_line [0] = prev_line [0] = 0;
+ warnings_occurred = 0;
+}
+
+static int get_char (cfile)
+ FILE *cfile;
+{
+ int c = getc (cfile);
+ if (!ugflag) {
+ if (c == EOL) {
+ if (cur_line == line1) {
+ cur_line = line2;
+ prev_line = line1;
+ } else {
+ cur_line = line2;
+ prev_line = line1;
+ }
+ line++;
+ lpos = 1;
+ cur_line [0] = 0;
+ } else if (c != EOF) {
+ if (lpos <= 81) {
+ cur_line [lpos - 1] = c;
+ cur_line [lpos] = 0;
+ }
+ lpos++;
+ }
+ } else
+ ugflag = 0;
+ return c;
+}
+
+static int get_token (cfile)
+ FILE *cfile;
+{
+ int c;
+ int ttok;
+ static char tb [2];
+ int l, p, u;
+
+ do {
+ l = line;
+ p = lpos;
+ u = ugflag;
+
+ c = get_char (cfile);
+#ifdef OLD_LEXER
+ if (c == '\n' && p == 1 && !u
+ && comment_index < sizeof comments)
+ comments [comment_index++] = '\n';
+#endif
+
+ if (!(c == '\n' && eol_token) && isascii (c) && isspace (c))
+ continue;
+ if (c == '#') {
+#ifdef OLD_LEXER
+ if (comment_index < sizeof comments)
+ comments [comment_index++] = '#';
+#endif
+ skip_to_eol (cfile);
+ continue;
+ }
+ if (c == '"') {
+ lexline = l;
+ lexchar = p;
+ ttok = read_string (cfile);
+ break;
+ }
+ if ((isascii (c) && isdigit (c)) || c == '-') {
+ lexline = l;
+ lexchar = p;
+ ttok = read_number (c, cfile);
+ break;
+ } else if (isascii (c) && isalpha (c)) {
+ lexline = l;
+ lexchar = p;
+ ttok = read_num_or_name (c, cfile);
+ break;
+ } else {
+ lexline = l;
+ lexchar = p;
+ tb [0] = c;
+ tb [1] = 0;
+ tval = tb;
+ ttok = c;
+ break;
+ }
+ } while (1);
+ return ttok;
+}
+
+int next_token (rval, cfile)
+ char **rval;
+ FILE *cfile;
+{
+ int rv;
+
+ if (token) {
+ if (lexline != tline)
+ token_line = cur_line;
+ lexchar = tlpos;
+ lexline = tline;
+ rv = token;
+ token = 0;
+ } else {
+ rv = get_token (cfile);
+ token_line = cur_line;
+ }
+ if (rval)
+ *rval = tval;
+#ifdef DEBUG_TOKENS
+ fprintf (stderr, "%s:%d ", tval, rv);
+#endif
+ return rv;
+}
+
+int peek_token (rval, cfile)
+ char **rval;
+ FILE *cfile;
+{
+ int x;
+
+ if (!token) {
+ tlpos = lexchar;
+ tline = lexline;
+ token = get_token (cfile);
+ if (lexline != tline)
+ token_line = prev_line;
+ x = lexchar; lexchar = tlpos; tlpos = x;
+ x = lexline; lexline = tline; tline = x;
+ }
+ if (rval)
+ *rval = tval;
+#ifdef DEBUG_TOKENS
+ fprintf (stderr, "(%s:%d) ", tval, token);
+#endif
+ return token;
+}
+
+static void skip_to_eol (cfile)
+ FILE *cfile;
+{
+ int c;
+ do {
+ c = get_char (cfile);
+ if (c == EOF)
+ return;
+#ifdef OLD_LEXER
+ if (comment_index < sizeof (comments))
+ comments [comment_index++] = c;
+#endif
+ if (c == EOL) {
+ return;
+ }
+ } while (1);
+}
+
+static int read_string (cfile)
+ FILE *cfile;
+{
+ int i;
+ int bs = 0;
+ int c;
+
+ for (i = 0; i < sizeof tokbuf; i++) {
+ c = get_char (cfile);
+ if (c == EOF) {
+ parse_warn ("eof in string constant");
+ break;
+ }
+ if (bs) {
+ bs = 0;
+ tokbuf [i] = c;
+ } else if (c == '\\')
+ bs = 1;
+ else if (c == '"')
+ break;
+ else
+ tokbuf [i] = c;
+ }
+ /* Normally, I'd feel guilty about this, but we're talking about
+ strings that'll fit in a DHCP packet here... */
+ if (i == sizeof tokbuf) {
+ parse_warn ("string constant larger than internal buffer");
+ --i;
+ }
+ tokbuf [i] = 0;
+ tval = tokbuf;
+ return STRING;
+}
+
+static int read_number (c, cfile)
+ int c;
+ FILE *cfile;
+{
+ int seenx = 0;
+ int i = 0;
+ int token = NUMBER;
+
+ tokbuf [i++] = c;
+ for (; i < sizeof tokbuf; i++) {
+ c = get_char (cfile);
+ if (!seenx && c == 'x') {
+ seenx = 1;
+#ifndef OLD_LEXER
+ } else if (isascii (c) && !isxdigit (c) &&
+ (c == '-' || c == '_' || isalpha (c))) {
+ token = NAME;
+ } else if (isascii (c) && !isdigit (c) && isxdigit (c)) {
+ token = NUMBER_OR_NAME;
+#endif
+ } else if (!isascii (c) || !isxdigit (c)) {
+ ungetc (c, cfile);
+ ugflag = 1;
+ break;
+ }
+ tokbuf [i] = c;
+ }
+ if (i == sizeof tokbuf) {
+ parse_warn ("numeric token larger than internal buffer");
+ --i;
+ }
+ tokbuf [i] = 0;
+ tval = tokbuf;
+ return token;
+}
+
+static int read_num_or_name (c, cfile)
+ int c;
+ FILE *cfile;
+{
+ int i = 0;
+ int rv = NUMBER_OR_NAME;
+ tokbuf [i++] = c;
+ for (; i < sizeof tokbuf; i++) {
+ c = get_char (cfile);
+ if (!isascii (c) ||
+ (c != '-' && c != '_' && !isalnum (c))) {
+ ungetc (c, cfile);
+ ugflag = 1;
+ break;
+ }
+ if (!isxdigit (c))
+ rv = NAME;
+ tokbuf [i] = c;
+ }
+ if (i == sizeof tokbuf) {
+ parse_warn ("token larger than internal buffer");
+ --i;
+ }
+ tokbuf [i] = 0;
+ tval = tokbuf;
+ return intern (tval, rv);
+}
+
+static int intern (atom, dfv)
+ char *atom;
+ int dfv;
+{
+ if (!isascii (atom [0]))
+ return dfv;
+
+ switch (tolower (atom [0])) {
+ case 'a':
+ if (!strcasecmp (atom + 1, "ppend"))
+ return APPEND;
+ if (!strcasecmp (atom + 1, "llow"))
+ return ALLOW;
+ if (!strcasecmp (atom + 1, "lias"))
+ return ALIAS;
+ if (!strcasecmp (atom + 1, "bandoned"))
+ return ABANDONED;
+ break;
+ case 'b':
+ if (!strcasecmp (atom + 1, "ackoff-cutoff"))
+ return BACKOFF_CUTOFF;
+ if (!strcasecmp (atom + 1, "ootp"))
+ return BOOTP;
+ if (!strcasecmp (atom + 1, "ooting"))
+ return BOOTING;
+ if (!strcasecmp (atom + 1, "oot-unknown-clients"))
+ return BOOT_UNKNOWN_CLIENTS;
+ case 'c':
+ if (!strcasecmp (atom + 1, "lass"))
+ return CLASS;
+ if (!strcasecmp (atom + 1, "iaddr"))
+ return CIADDR;
+ if (!strcasecmp (atom + 1, "lient-identifier"))
+ return CLIENT_IDENTIFIER;
+ if (!strcasecmp (atom + 1, "lient-hostname"))
+ return CLIENT_HOSTNAME;
+ break;
+ case 'd':
+ if (!strcasecmp (atom + 1, "omain"))
+ return DOMAIN;
+ if (!strcasecmp (atom + 1, "eny"))
+ return DENY;
+ if (!strncasecmp (atom + 1, "efault", 6)) {
+ if (!atom [7])
+ return DEFAULT;
+ if (!strcasecmp (atom + 7, "-lease-time"))
+ return DEFAULT_LEASE_TIME;
+ break;
+ }
+ if (!strncasecmp (atom + 1, "ynamic-bootp", 12)) {
+ if (!atom [13])
+ return DYNAMIC_BOOTP;
+ if (!strcasecmp (atom + 13, "-lease-cutoff"))
+ return DYNAMIC_BOOTP_LEASE_CUTOFF;
+ if (!strcasecmp (atom + 13, "-lease-length"))
+ return DYNAMIC_BOOTP_LEASE_LENGTH;
+ break;
+ }
+ break;
+ case 'e':
+ if (!strcasecmp (atom + 1, "thernet"))
+ return ETHERNET;
+ if (!strcasecmp (atom + 1, "nds"))
+ return ENDS;
+ if (!strcasecmp (atom + 1, "xpire"))
+ return EXPIRE;
+ break;
+ case 'f':
+ if (!strcasecmp (atom + 1, "ilename"))
+ return FILENAME;
+ if (!strcasecmp (atom + 1, "ixed-address"))
+ return FIXED_ADDR;
+ break;
+ case 'g':
+ if (!strcasecmp (atom + 1, "iaddr"))
+ return GIADDR;
+ if (!strcasecmp (atom + 1, "roup"))
+ return GROUP;
+ if (!strcasecmp (atom + 1, "et-lease-hostnames"))
+ return GET_LEASE_HOSTNAMES;
+ break;
+ case 'h':
+ if (!strcasecmp (atom + 1, "ost"))
+ return HOST;
+ if (!strcasecmp (atom + 1, "ardware"))
+ return HARDWARE;
+ if (!strcasecmp (atom + 1, "ostname"))
+ return HOSTNAME;
+ break;
+ case 'i':
+ if (!strcasecmp (atom + 1, "nitial-interval"))
+ return INITIAL_INTERVAL;
+ if (!strcasecmp (atom + 1, "nterface"))
+ return INTERFACE;
+ break;
+ case 'l':
+ if (!strcasecmp (atom + 1, "ease"))
+ return LEASE;
+ break;
+ case 'm':
+ if (!strcasecmp (atom + 1, "ax-lease-time"))
+ return MAX_LEASE_TIME;
+ if (!strncasecmp (atom + 1, "edi", 3)) {
+ if (!strcasecmp (atom + 4, "a"))
+ return MEDIA;
+ if (!strcasecmp (atom + 4, "um"))
+ return MEDIUM;
+ break;
+ }
+ break;
+ case 'n':
+ if (!strcasecmp (atom + 1, "ameserver"))
+ return NAMESERVER;
+ if (!strcasecmp (atom + 1, "etmask"))
+ return NETMASK;
+ if (!strcasecmp (atom + 1, "ext-server"))
+ return NEXT_SERVER;
+ break;
+ case 'o':
+ if (!strcasecmp (atom + 1, "ption"))
+ return OPTION;
+ if (!strcasecmp (atom + 1, "ne-lease-per-client"))
+ return ONE_LEASE_PER_CLIENT;
+ break;
+ case 'p':
+ if (!strcasecmp (atom + 1, "repend"))
+ return PREPEND;
+ if (!strcasecmp (atom + 1, "acket"))
+ return PACKET;
+ break;
+ case 'r':
+ if (!strcasecmp (atom + 1, "ange"))
+ return RANGE;
+ if (!strcasecmp (atom + 1, "equest"))
+ return REQUEST;
+ if (!strcasecmp (atom + 1, "equire"))
+ return REQUIRE;
+ if (!strcasecmp (atom + 1, "etry"))
+ return RETRY;
+ if (!strcasecmp (atom + 1, "enew"))
+ return RENEW;
+ if (!strcasecmp (atom + 1, "ebind"))
+ return REBIND;
+ if (!strcasecmp (atom + 1, "eboot"))
+ return REBOOT;
+ if (!strcasecmp (atom + 1, "eject"))
+ return REJECT;
+ break;
+ case 's':
+ if (!strcasecmp (atom + 1, "earch"))
+ return SEARCH;
+ if (!strcasecmp (atom + 1, "tarts"))
+ return STARTS;
+ if (!strcasecmp (atom + 1, "iaddr"))
+ return SIADDR;
+ if (!strcasecmp (atom + 1, "ubnet"))
+ return SUBNET;
+ if (!strcasecmp (atom + 1, "hared-network"))
+ return SHARED_NETWORK;
+ if (!strcasecmp (atom + 1, "erver-name"))
+ return SERVER_NAME;
+ if (!strcasecmp (atom + 1, "erver-identifier"))
+ return SERVER_IDENTIFIER;
+ if (!strcasecmp (atom + 1, "elect-timeout"))
+ return SELECT_TIMEOUT;
+ if (!strcasecmp (atom + 1, "end"))
+ return SEND;
+ if (!strcasecmp (atom + 1, "cript"))
+ return SCRIPT;
+ if (!strcasecmp (atom + 1, "upersede"))
+ return SUPERSEDE;
+ break;
+ case 't':
+ if (!strcasecmp (atom + 1, "imestamp"))
+ return TIMESTAMP;
+ if (!strcasecmp (atom + 1, "imeout"))
+ return TIMEOUT;
+ if (!strcasecmp (atom + 1, "oken-ring"))
+ return TOKEN_RING;
+ break;
+ case 'u':
+ if (!strcasecmp (atom + 1, "id"))
+ return UID;
+ if (!strcasecmp (atom + 1, "ser-class"))
+ return USER_CLASS;
+ if (!strcasecmp (atom + 1, "se-host-decl-names"))
+ return USE_HOST_DECL_NAMES;
+ if (!strcasecmp (atom + 1, "nknown-clients"))
+ return UNKNOWN_CLIENTS;
+ break;
+ case 'v':
+ if (!strcasecmp (atom + 1, "endor-class"))
+ return VENDOR_CLASS;
+ break;
+ case 'y':
+ if (!strcasecmp (atom + 1, "iaddr"))
+ return YIADDR;
+ break;
+ }
+ return dfv;
+}
diff --git a/contrib/isc-dhcp/common/convert.c b/contrib/isc-dhcp/common/convert.c
new file mode 100644
index 000000000000..42f488b308e8
--- /dev/null
+++ b/contrib/isc-dhcp/common/convert.c
@@ -0,0 +1,118 @@
+/* convert.c
+
+ Safe copying of option values into and out of the option buffer, which
+ can't be assumed to be aligned. */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: convert.c,v 1.4.2.1 1998/06/25 21:11:28 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+u_int32_t getULong (buf)
+ unsigned char *buf;
+{
+ unsigned long ibuf;
+
+ memcpy (&ibuf, buf, sizeof (u_int32_t));
+ return ntohl (ibuf);
+}
+
+int32_t getLong (buf)
+ unsigned char *buf;
+{
+ long ibuf;
+
+ memcpy (&ibuf, buf, sizeof (int32_t));
+ return ntohl (ibuf);
+}
+
+u_int16_t getUShort (buf)
+ unsigned char *buf;
+{
+ unsigned short ibuf;
+
+ memcpy (&ibuf, buf, sizeof (u_int16_t));
+ return ntohs (ibuf);
+}
+
+int16_t getShort (buf)
+ unsigned char *buf;
+{
+ short ibuf;
+
+ memcpy (&ibuf, buf, sizeof (int16_t));
+ return ntohs (ibuf);
+}
+
+void putULong (obuf, val)
+ unsigned char *obuf;
+ u_int32_t val;
+{
+ u_int32_t tmp = htonl (val);
+ memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putLong (obuf, val)
+ unsigned char *obuf;
+ int32_t val;
+{
+ int32_t tmp = htonl (val);
+ memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putUShort (obuf, val)
+ unsigned char *obuf;
+ unsigned int val;
+{
+ u_int16_t tmp = htons (val);
+ memcpy (obuf, &tmp, sizeof tmp);
+}
+
+void putShort (obuf, val)
+ unsigned char *obuf;
+ int val;
+{
+ int16_t tmp = htons (val);
+ memcpy (obuf, &tmp, sizeof tmp);
+}
+
diff --git a/contrib/isc-dhcp/common/dhcp-options.5 b/contrib/isc-dhcp/common/dhcp-options.5
new file mode 100644
index 000000000000..eb90ed6eac9b
--- /dev/null
+++ b/contrib/isc-dhcp/common/dhcp-options.5
@@ -0,0 +1,451 @@
+.\" dhcp-options.5
+.\"
+.\" Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of The Internet Software Consortium nor the names
+.\" of its contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" This software has been written for the Internet Software Consortium
+.\" by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+.\" Enterprises. To learn more about the Internet Software Consortium,
+.\" see ``http://www.isc.org/isc''. To learn more about Vixie
+.\" Enterprises, see ``http://www.vix.com''.
+.TH dhcpd-options 5
+.SH NAME
+dhcp-options - Dynamic Host Configuration Protocol options
+.SH DESCRIPTION
+The Dynamic Host Configuration protocol allows the client to receive
+.B options
+from the DHCP server describing the network configuration and various
+services that are available on the network. When configuring
+.B dhcpd(8)
+or
+.B dhclient(8) ,
+options must often be declared. The syntax for declaring options,
+and the names and formats of the options that can be declared, are
+documented here.
+.SH REFERENCE: OPTION STATEMENTS
+.PP
+DHCP \fIoption\fR statements always start with the \fIoption\fR
+keyword, followed by an option name, followed by option data. The
+option names and data formats are described below. It is not
+necessary to exhaustively specify all DHCP options - only those
+options which are needed by clients must be specified.
+.PP
+Option data comes in a variety of formats, as defined below:
+.PP
+The
+.B ip-address
+data type can be entered either as an explicit IP
+address (e.g., 239.254.197.10) or as a domain name (e.g.,
+haagen.isc.org). When entering a domain name, be sure that that
+domain name resolves to a single IP address.
+.PP
+The
+.B int32
+data type specifies a signed 32-bit integer. The
+.B uint32
+data type specifies an unsigned 32-bit integer. The
+.B int16
+and
+.B uint16
+data types specify signed and unsigned 16-bit integers. The
+.B int8
+and
+.B uint8
+data types specify signed and unsigned 8-bit integers.
+Unsigned 8-bit integers are also sometimes referred to as octets.
+.PP
+The
+.B string
+data type specifies an NVT ASCII string, which must be
+enclosed in double quotes - for example, to specify a domain-name
+option, the syntax would be
+.nf
+.sp 1
+ option domain-name "isc.org";
+.fi
+.PP
+The
+.B flag
+data type specifies a boolean value. Booleans can be either true or
+false (or on or off, if that makes more sense to you).
+.PP
+The
+.B data-string
+data type specifies either an NVT ASCII string
+enclosed in double quotes, or a series of octets specified in
+hexadecimal, seperated by colons. For example:
+.nf
+.sp 1
+ option client-identifier "CLIENT-FOO";
+or
+ option client-identifier 43:4c:49:45:54:2d:46:4f:4f;
+.fi
+.PP
+The documentation for the various options mentioned below is taken
+from the latest IETF draft document on DHCP options. Options which
+are not listed by name may be defined by the name option-\fInnn\fR,
+where \fInnn\fI is the decimal number of the option code. These
+options may be followed either by a string, enclosed in quotes, or by
+a series of octets, expressed as two-digit hexadecimal numbers seperated
+by colons. For example:
+.PP
+.nf
+ option option-133 "my-option-133-text";
+ option option-129 1:54:c9:2b:47;
+.fi
+.PP
+Because dhcpd does not know the format of these undefined option codes,
+no checking is done to ensure the correctness of the entered data.
+.PP
+The standard options are:
+.PP
+ \fBoption subnet-mask\fR \fIip-address\fR\fB;\fR
+.PP
+The subnet mask option specifies the client's subnet mask as per RFC
+950. If no subnet mask option is provided anywhere in scope, as a
+last resort dhcpd will use the subnet mask from the subnet declaration
+for the network on which an address is being assigned. However,
+.I any
+subnet-mask option declaration that is in scope for the address being
+assigned will override the subnet mask specified in the subnet
+declaration.
+.PP
+ \fBoption time-offset\fR \fIint32\fR\fB;\fR
+.PP
+The time-offset option specifies the offset of the client's subnet in
+seconds from Coordinated Universal Time (UTC).
+.PP
+ \fBoption routers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The routers option specifies a list of IP addresses for routers on the
+client's subnet. Routers should be listed in order of preference.
+.PP
+ \fBoption time-servers\fR \fIip-address [, \fIip-address\fR ... ]\fB;\fR
+.PP
+The time-server option specifies a list of RFC 868 time servers
+available to the client. Servers should be listed in order of
+preference.
+.PP
+ \fBoption\fR \fBien116-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ];
+.PP
+The ien116-name-servers option specifies a list of IEN 116 name servers
+available to the client. Servers should be listed in order of
+preference.
+.PP
+ \fBoption\fR \fBdomain-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The domain-name-servers option specifies a list of Domain Name System
+(STD 13, RFC 1035) name servers available to the client. Servers
+should be listed in order of preference.
+.PP
+ \fBoption\fR \fBlog-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The log-server option specifies a list of MIT-LCS UDP log servers
+available to the client. Servers should be listed in order of
+preference.
+.PP
+ \fBoption\fR \fBcookie-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The cookie server option specifies a list of RFC 865 cookie
+servers available to the client. Servers should be listed in order
+of preference.
+.PP
+ \fBoption\fR \fBlpr-servers\fR \fIip-address \fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The LPR server option specifies a list of RFC 1179 line printer
+servers available to the client. Servers should be listed in order
+of preference.
+.PP
+ \fBoption\fR \fBimpress-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The impress-server option specifies a list of Imagen Impress servers
+available to the client. Servers should be listed in order of
+preference.
+.PP
+ \fBoption\fR \fBresource-location-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+This option specifies a list of RFC 887 Resource Location
+servers available to the client. Servers should be listed in order
+of preference.
+.PP
+ \fBoption\fR \fBhost-name\fR \fIstring\fR\fB;\fR
+.PP
+This option specifies the name of the client. The name may or may
+not be qualified with the local domain name (it is preferable to use
+the domain-name option to specify the domain name). See RFC 1035 for
+character set restrictions.
+.PP
+ \fBoption\fR \fBboot-size\fR \fIuint16\fR\fB;\fR
+.PP
+This option specifies the length in 512-octet blocks of the default
+boot image for the client.
+.PP
+ \fBoption\fR \fBmerit-dump\fR \fIstring\fR\fB;\fR
+.PP
+This option specifies the path-name of a file to which the client's
+core image should be dumped in the event the client crashes. The
+path is formatted as a character string consisting of characters from
+the NVT ASCII character set.
+.PP
+ \fBoption\fR \fBdomain-name\fR \fIstring\fR\fB;\fR
+.PP
+This option specifies the domain name that client should use when
+resolving hostnames via the Domain Name System.
+.PP
+ \fBoption\fR \fBswap-server\fR \fIip-address\fR\fB;\fR
+.PP
+This specifies the IP address of the client's swap server.
+.PP
+ \fBoption\fR \fBroot-path\fR \fIstring\fB;\fR\fR
+.PP
+This option specifies the path-name that contains the client's root
+disk. The path is formatted as a character string consisting of
+characters from the NVT ASCII character set.
+.PP
+ \fBoption\fR \fBip-forwarding\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether the client should configure its IP
+layer for packet forwarding. A value of 0 means disable IP
+forwarding, and a value of 1 means enable IP forwarding.
+.PP
+ \fBoption\fR \fBnon-local-source-routing\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether the client should configure its IP
+layer to allow forwarding of datagrams with non-local source routes
+(see Section 3.3.5 of [4] for a discussion of this topic). A value
+of 0 means disallow forwarding of such datagrams, and a value of 1
+means allow forwarding.
+.PP
+ \fBoption\fR \fBpolicy-filter\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR ... ]\fB;\fR
+.PP
+This option specifies policy filters for non-local source routing.
+The filters consist of a list of IP addresses and masks which specify
+destination/mask pairs with which to filter incoming source routes.
+.PP
+Any source routed datagram whose next-hop address does not match one
+of the filters should be discarded by the client.
+.PP
+See STD 3 (RFC1122) for further information.
+.PP
+ \fBoption\fR \fBmax-dgram-reassembly\fR \fIuint16\fR\fB;\fR
+.PP
+This option specifies the maximum size datagram that the client
+should be prepared to reassemble. The minimum value legal value is
+576.
+.PP
+ \fBoption\fR \fBdefault-ip-ttl\fR \fIuint8;\fR
+.PP
+This option specifies the default time-to-live that the client should
+use on outgoing datagrams.
+.PP
+ \fBoption\fR \fBpath-mtu-aging-timeout\fR \fIuint32\fR\fB;\fR
+.PP
+This option specifies the timeout (in seconds) to use when aging Path
+MTU values discovered by the mechanism defined in RFC 1191.
+.PP
+ \fBoption\fR \fBpath-mtu-plateau-table\fR \fIuint16\fR [\fB,\fR \fIuint16\fR ... ]\fB;\fR
+.PP
+This option specifies a table of MTU sizes to use when performing
+Path MTU Discovery as defined in RFC 1191. The table is formatted as
+a list of 16-bit unsigned integers, ordered from smallest to largest.
+The minimum MTU value cannot be smaller than 68.
+.PP
+ \fBoption\fR \fBinterface-mtu\fR \fIuint16\fR\fB;\fR
+.PP
+This option specifies the MTU to use on this interface. The minimum
+legal value for the MTU is 68.
+.PP
+ \fBoption\fR \fBall-subnets-local\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether or not the client may assume that all
+subnets of the IP network to which the client is connected use the
+same MTU as the subnet of that network to which the client is
+directly connected. A value of 1 indicates that all subnets share
+the same MTU. A value of 0 means that the client should assume that
+some subnets of the directly connected network may have smaller MTUs.
+.PP
+ \fBoption\fR \fBbroadcast-address\fR \fIip-address\fR\fB;\fR
+.PP
+This option specifies the broadcast address in use on the client's
+subnet. Legal values for broadcast addresses are specified in
+section 3.2.1.3 of STD 3 (RFC1122).
+.PP
+ \fBoption\fR \fBperform-mask-discovery\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether or not the client should perform subnet
+mask discovery using ICMP. A value of 0 indicates that the client
+should not perform mask discovery. A value of 1 means that the
+client should perform mask discovery.
+.PP
+ \fBoption\fR \fBmask-supplier\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether or not the client should respond to
+subnet mask requests using ICMP. A value of 0 indicates that the
+client should not respond. A value of 1 means that the client should
+respond.
+.PP
+ \fBoption\fR \fBrouter-discovery\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether or not the client should solicit
+routers using the Router Discovery mechanism defined in RFC 1256.
+A value of 0 indicates that the client should not perform
+router discovery. A value of 1 means that the client should perform
+router discovery.
+.PP
+ \fBoption\fR \fBrouter-solicitation-address\fR \fIip-address\fR\fB;\fR
+.PP
+This option specifies the address to which the client should transmit
+router solicitation requests.
+.PP
+ \fBoption\fR \fBstatic-routes\fR \fIip-address ip-address\fR [\fB,\fR \fIip-address ip-address\fR ... ]\fB;\fR
+.PP
+This option specifies a list of static routes that the client should
+install in its routing cache. If multiple routes to the same
+destination are specified, they are listed in descending order of
+priority.
+.PP
+The routes consist of a list of IP address pairs. The first address
+is the destination address, and the second address is the router for
+the destination.
+.PP
+The default route (0.0.0.0) is an illegal destination for a static
+route. To specify the default route, use the
+.B routers
+option.
+.PP
+ \fBoption\fR \fBtrailer-encapsulation\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether or not the client should negotiate the
+use of trailers (RFC 893 [14]) when using the ARP protocol. A value
+of 0 indicates that the client should not attempt to use trailers. A
+value of 1 means that the client should attempt to use trailers.
+.PP
+ \fBoption\fR \fBarp-cache-timeout\fR \fIuint32\fR\fB;\fR
+.PP
+This option specifies the timeout in seconds for ARP cache entries.
+.PP
+ \fBoption\fR \fBieee802-3-encapsulation\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies whether or not the client should use Ethernet
+Version 2 (RFC 894) or IEEE 802.3 (RFC 1042) encapsulation if the
+interface is an Ethernet. A value of 0 indicates that the client
+should use RFC 894 encapsulation. A value of 1 means that the client
+should use RFC 1042 encapsulation.
+.PP
+ \fBoption\fR \fBdefault-tcp-ttl\fR \fIuint8\fR\fB;\fR
+.PP
+This option specifies the default TTL that the client should use when
+sending TCP segments. The minimum value is 1.
+.PP
+ \fBoption\fR \fBtcp-keepalive-interval\fR \fIuint32\fR\fB;\fR
+.PP
+This option specifies the interval (in seconds) that the client TCP
+should wait before sending a keepalive message on a TCP connection.
+The time is specified as a 32-bit unsigned integer. A value of zero
+indicates that the client should not generate keepalive messages on
+connections unless specifically requested by an application.
+.PP
+ \fBoption\fR \fBtcp-keepalive-garbage\fR \fIflag\fR\fB;\fR
+.PP
+This option specifies the whether or not the client should send TCP
+keepalive messages with a octet of garbage for compatibility with
+older implementations. A value of 0 indicates that a garbage octet
+should not be sent. A value of 1 indicates that a garbage octet
+should be sent.
+.PP
+ \fBoption\fR \fBnis-domain\fR \fIstring\fR\fB;\fR
+.PP
+This option specifies the name of the client's NIS (Sun Network
+Information Services) domain. The domain is formatted as a character
+string consisting of characters from the NVT ASCII character set.
+.PP
+ \fBoption\fR \fBnis-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+This option specifies a list of IP addresses indicating NIS servers
+available to the client. Servers should be listed in order of
+preference.
+.PP
+ \fBoption\fR \fBntp-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+This option specifies a list of IP addresses indicating NTP (RFC 1035)
+servers available to the client. Servers should be listed in order
+of preference.
+.PP
+ \fBoption\fR \fBnetbios-name-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The NetBIOS name server (NBNS) option specifies a list of RFC
+1001/1002 NBNS name servers listed in order of preference.
+.PP
+ \fBoption\fR \fBnetbios-dd-server\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+The NetBIOS datagram distribution server (NBDD) option specifies a
+list of RFC 1001/1002 NBDD servers listed in order of preference.
+.PP
+ \fBoption\fR \fBnetbios-node-type\fR \fIuint8\fR\fB;\fR
+.PP
+The NetBIOS node type option allows NetBIOS over TCP/IP clients which
+are configurable to be configured as described in RFC 1001/1002. The
+value is specified as a single octet which identifies the client type.
+A value of 1 corresponds to a NetBIOS B-node; a value of 2 corresponds
+to a P-node; a value of 4 corresponds to an M-node; a value of 8
+corresponds to an H-node.
+.PP
+ \fBoption\fR \fBnetbios-scope\fR \fIstring\fR\fB;\fR
+.PP
+The NetBIOS scope option specifies the NetBIOS over TCP/IP scope
+parameter for the client as specified in RFC 1001/1002. See RFC1001,
+RFC1002, and RFC1035 for character-set restrictions.
+.PP
+ \fBoption\fR \fBfont-servers\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+This option specifies a list of X Window System Font servers available
+to the client. Servers should be listed in order of preference.
+.PP
+ \fBoption\fR \fBx-display-manager\fR \fIip-address\fR [\fB,\fR \fIip-address\fR ... ]\fB;\fR
+.PP
+This option specifies a list of systems that are running the X Window
+System Display Manager and are available to the client. Addresses
+should be listed in order of preference.
+.PP
+ \fBoption\fR \fBdhcp-client-identifier\fR \fIdata-string\fR\fB;\fR
+.PP
+This option can be used to specify the a DHCP client identifier in a
+host declaration, so that dhcpd can find the host record by matching
+against the client identifier.
+.SH SEE ALSO
+dhcpd.conf(5), dhcpd.leases(5), dhclient.conf(5), dhcpd(8),
+dhclient(8), RFC2132, RFC2131.
+.SH AUTHOR
+.B dhcpd(8)
+was written by Ted Lemon <mellon@vix.com>
+under a contract with Vixie Labs. Funding
+for this project was provided by the Internet Software Corporation.
+Information about the Internet Software Consortium can be found at
+.B http://www.isc.org/isc.
diff --git a/contrib/isc-dhcp/common/dispatch.c b/contrib/isc-dhcp/common/dispatch.c
new file mode 100644
index 000000000000..92fd579b70ab
--- /dev/null
+++ b/contrib/isc-dhcp/common/dispatch.c
@@ -0,0 +1,750 @@
+/* dispatch.c
+
+ Network input dispatcher... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: dispatch.c,v 1.47.2.2 1998/06/25 21:11:28 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <sys/ioctl.h>
+
+struct interface_info *interfaces, *dummy_interfaces;
+struct protocol *protocols;
+struct timeout *timeouts;
+static struct timeout *free_timeouts;
+static int interfaces_invalidated;
+void (*bootp_packet_handler) PROTO ((struct interface_info *,
+ struct dhcp_packet *, int, unsigned int,
+ struct iaddr, struct hardware *));
+
+static void got_one PROTO ((struct protocol *));
+int quiet_interface_discovery;
+
+/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
+ For each interface that's of type INET and not the loopback interface,
+ register that interface with the network I/O software, figure out what
+ subnet it's on, and add it to the list of interfaces. */
+
+void discover_interfaces (state)
+ int state;
+{
+ struct interface_info *tmp;
+ struct interface_info *last, *next;
+ char buf [8192];
+ struct ifconf ic;
+ struct ifreq ifr;
+ int i;
+ int sock;
+ int address_count = 0;
+ struct subnet *subnet;
+ struct shared_network *share;
+ struct sockaddr_in foo;
+ int ir;
+#ifdef ALIAS_NAMES_PERMUTED
+ char *s;
+#endif
+#ifdef USE_FALLBACK
+ static struct shared_network fallback_network;
+#endif
+
+ /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
+ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ error ("Can't create addrlist socket");
+
+ /* Get the interface configuration information... */
+ ic.ifc_len = sizeof buf;
+ ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+ i = ioctl(sock, SIOCGIFCONF, &ic);
+
+ if (i < 0)
+ error ("ioctl: SIOCGIFCONF: %m");
+
+ /* If we already have a list of interfaces, and we're running as
+ a DHCP server, the interfaces were requested. */
+ if (interfaces && (state == DISCOVER_SERVER ||
+ state == DISCOVER_RELAY ||
+ state == DISCOVER_REQUESTED))
+ ir = 0;
+ else if (state == DISCOVER_UNCONFIGURED)
+ ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC;
+ else
+ ir = INTERFACE_REQUESTED;
+
+ /* Cycle through the list of interfaces looking for IP addresses.
+ Go through twice; once to count the number of addresses, and a
+ second time to copy them into an array of addresses. */
+ for (i = 0; i < ic.ifc_len;) {
+ struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
+#ifdef HAVE_SA_LEN
+ if (ifp -> ifr_addr.sa_len)
+ i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len;
+ else
+#endif
+ i += sizeof *ifp;
+
+#ifdef ALIAS_NAMES_PERMUTED
+ if ((s = strrchr (ifp -> ifr_name, ':'))) {
+ *s = 0;
+ }
+#endif
+
+#ifdef SKIP_DUMMY_INTERFACES
+ if (!strncmp (ifp -> ifr_name, "dummy", 5))
+ continue;
+#endif
+
+
+ /* See if this is the sort of interface we want to
+ deal with. */
+ strcpy (ifr.ifr_name, ifp -> ifr_name);
+ if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)
+ error ("Can't get interface flags for %s: %m",
+ ifr.ifr_name);
+
+ /* Skip loopback, point-to-point and down interfaces,
+ except don't skip down interfaces if we're trying to
+ get a list of configurable interfaces. */
+ if ((ifr.ifr_flags & IFF_LOOPBACK) ||
+#ifdef IFF_POINTOPOINT
+ (ifr.ifr_flags & IFF_POINTOPOINT) ||
+#endif
+ (!(ifr.ifr_flags & IFF_UP) &&
+ state != DISCOVER_UNCONFIGURED))
+ continue;
+
+ /* See if we've seen an interface that matches this one. */
+ for (tmp = interfaces; tmp; tmp = tmp -> next)
+ if (!strcmp (tmp -> name, ifp -> ifr_name))
+ break;
+
+ /* If there isn't already an interface by this name,
+ allocate one. */
+ if (!tmp) {
+ tmp = ((struct interface_info *)
+ dmalloc (sizeof *tmp, "discover_interfaces"));
+ if (!tmp)
+ error ("Insufficient memory to %s %s",
+ "record interface", ifp -> ifr_name);
+ strcpy (tmp -> name, ifp -> ifr_name);
+ tmp -> next = interfaces;
+ tmp -> flags = ir;
+ interfaces = tmp;
+ }
+
+ /* If we have the capability, extract link information
+ and record it in a linked list. */
+#ifdef AF_LINK
+ if (ifp -> ifr_addr.sa_family == AF_LINK) {
+ struct sockaddr_dl *foo = ((struct sockaddr_dl *)
+ (&ifp -> ifr_addr));
+ tmp -> hw_address.hlen = foo -> sdl_alen;
+ tmp -> hw_address.htype = HTYPE_ETHER; /* XXX */
+ memcpy (tmp -> hw_address.haddr,
+ LLADDR (foo), foo -> sdl_alen);
+ } else
+#endif /* AF_LINK */
+
+ if (ifp -> ifr_addr.sa_family == AF_INET) {
+ struct iaddr addr;
+
+#if defined (SIOCGIFHWADDR) && !defined (AF_LINK)
+ struct ifreq ifr;
+ struct sockaddr sa;
+ int b, sk;
+
+ /* Read the hardware address from this interface. */
+ ifr = *ifp;
+ if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0)
+ error ("Can't get hardware address for %s: %m",
+ ifr.ifr_name);
+
+ sa = *(struct sockaddr *)&ifr.ifr_hwaddr;
+
+ switch (sa.sa_family) {
+#ifdef ARPHRD_LOOPBACK
+ case ARPHRD_LOOPBACK:
+ /* ignore loopback interface */
+ break;
+#endif
+
+ case ARPHRD_ETHER:
+ tmp -> hw_address.hlen = 6;
+ tmp -> hw_address.htype = ARPHRD_ETHER;
+ memcpy (tmp -> hw_address.haddr,
+ sa.sa_data, 6);
+ break;
+
+#ifndef ARPHRD_IEEE802
+# define ARPHRD_IEEE802 HTYPE_IEEE802
+#endif
+ case ARPHRD_IEEE802:
+ tmp -> hw_address.hlen = 6;
+ tmp -> hw_address.htype = ARPHRD_IEEE802;
+ memcpy (tmp -> hw_address.haddr,
+ sa.sa_data, 6);
+ break;
+
+#ifdef ARPHRD_METRICOM
+ case ARPHRD_METRICOM:
+ tmp -> hw_address.hlen = 6;
+ tmp -> hw_address.htype = ARPHRD_METRICOM;
+ memcpy (tmp -> hw_address.haddr,
+ sa.sa_data, 6);
+
+ break;
+#endif
+
+ default:
+ error ("%s: unknown hardware address type %d",
+ ifr.ifr_name, sa.sa_family);
+ }
+#endif /* defined (SIOCGIFHWADDR) && !defined (AF_LINK) */
+
+ /* Get a pointer to the address... */
+ memcpy (&foo, &ifp -> ifr_addr,
+ sizeof ifp -> ifr_addr);
+
+ /* We don't want the loopback interface. */
+ if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK))
+ continue;
+
+
+ /* If this is the first real IP address we've
+ found, keep a pointer to ifreq structure in
+ which we found it. */
+ if (!tmp -> ifp) {
+ struct ifreq *tif;
+#ifdef HAVE_SA_LEN
+ int len = ((sizeof ifp -> ifr_name) +
+ ifp -> ifr_addr.sa_len);
+#else
+ int len = sizeof *ifp;
+#endif
+ tif = (struct ifreq *)malloc (len);
+ if (!tif)
+ error ("no space to remember ifp.");
+ memcpy (tif, ifp, len);
+ tmp -> ifp = tif;
+ tmp -> primary_address = foo.sin_addr;
+ }
+
+ /* Grab the address... */
+ addr.len = 4;
+ memcpy (addr.iabuf, &foo.sin_addr.s_addr,
+ addr.len);
+
+ /* If there's a registered subnet for this address,
+ connect it together... */
+ if ((subnet = find_subnet (addr))) {
+ /* If this interface has multiple aliases
+ on the same subnet, ignore all but the
+ first we encounter. */
+ if (!subnet -> interface) {
+ subnet -> interface = tmp;
+ subnet -> interface_address = addr;
+ } else if (subnet -> interface != tmp) {
+ warn ("Multiple %s %s: %s %s",
+ "interfaces match the",
+ "same subnet",
+ subnet -> interface -> name,
+ tmp -> name);
+ }
+ share = subnet -> shared_network;
+ if (tmp -> shared_network &&
+ tmp -> shared_network != share) {
+ warn ("Interface %s matches %s",
+ tmp -> name,
+ "multiple shared networks");
+ } else {
+ tmp -> shared_network = share;
+ }
+
+ if (!share -> interface) {
+ share -> interface = tmp;
+ } else if (share -> interface != tmp) {
+ warn ("Multiple %s %s: %s %s",
+ "interfaces match the",
+ "same shared network",
+ share -> interface -> name,
+ tmp -> name);
+ }
+ }
+ }
+ }
+
+ /* If we're just trying to get a list of interfaces that we might
+ be able to configure, we can quit now. */
+ if (state == DISCOVER_UNCONFIGURED)
+ return;
+
+ /* Weed out the interfaces that did not have IP addresses. */
+ last = (struct interface_info *)0;
+ for (tmp = interfaces; tmp; tmp = next) {
+ next = tmp -> next;
+ if ((tmp -> flags & INTERFACE_AUTOMATIC) &&
+ state == DISCOVER_REQUESTED)
+ tmp -> flags &= ~(INTERFACE_AUTOMATIC |
+ INTERFACE_REQUESTED);
+ if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
+ if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
+ error ("%s: not found", tmp -> name);
+ if (!last)
+ interfaces = interfaces -> next;
+ else
+ last -> next = tmp -> next;
+
+ /* Remember the interface in case we need to know
+ about it later. */
+ tmp -> next = dummy_interfaces;
+ dummy_interfaces = tmp;
+ continue;
+ }
+ last = tmp;
+
+ memcpy (&foo, &tmp -> ifp -> ifr_addr,
+ sizeof tmp -> ifp -> ifr_addr);
+
+ /* We must have a subnet declaration for each interface. */
+ if (!tmp -> shared_network && (state == DISCOVER_SERVER))
+ error ("No subnet declaration for %s (%s).",
+ tmp -> name, inet_ntoa (foo.sin_addr));
+
+ /* Find subnets that don't have valid interface
+ addresses... */
+ for (subnet = (tmp -> shared_network
+ ? tmp -> shared_network -> subnets
+ : (struct subnet *)0);
+ subnet; subnet = subnet -> next_sibling) {
+ if (!subnet -> interface_address.len) {
+ /* Set the interface address for this subnet
+ to the first address we found. */
+ subnet -> interface_address.len = 4;
+ memcpy (subnet -> interface_address.iabuf,
+ &foo.sin_addr.s_addr, 4);
+ }
+ }
+
+ /* Register the interface... */
+ if_register_receive (tmp);
+ if_register_send (tmp);
+ }
+
+ /* Now register all the remaining interfaces as protocols. */
+ for (tmp = interfaces; tmp; tmp = tmp -> next)
+ add_protocol (tmp -> name, tmp -> rfdesc, got_one, tmp);
+
+ close (sock);
+
+#ifdef USE_FALLBACK
+ strcpy (fallback_interface.name, "fallback");
+ fallback_interface.shared_network = &fallback_network;
+ fallback_network.name = "fallback-net";
+ if_register_fallback (&fallback_interface);
+ add_protocol ("fallback", fallback_interface.wfdesc,
+ fallback_discard, &fallback_interface);
+#endif
+}
+
+void reinitialize_interfaces ()
+{
+ struct interface_info *ip;
+
+ for (ip = interfaces; ip; ip = ip -> next) {
+ if_reinitialize_receive (ip);
+ if_reinitialize_send (ip);
+ }
+
+#ifdef USE_FALLBACK
+ if_reinitialize_fallback (&fallback_interface);
+#endif
+
+ interfaces_invalidated = 1;
+}
+
+#ifdef USE_POLL
+/* Wait for packets to come in using poll(). Anyway, when a packet
+ comes in, call receive_packet to receive the packet and possibly
+ strip hardware addressing information from it, and then call
+ do_packet to try to do something with it.
+
+ As you can see by comparing this with the code that uses select(),
+ below, this is gratuitously complex. Quelle surprise, eh? This is
+ SysV we're talking about, after all, and even in the 90's, it
+ wouldn't do for SysV to make networking *easy*, would it? Rant,
+ rant... */
+
+void dispatch ()
+{
+ struct protocol *l;
+ int nfds = 0;
+ struct pollfd *fds;
+ int count;
+ int i;
+ int to_msec;
+
+ nfds = 0;
+ for (l = protocols; l; l = l -> next) {
+ ++nfds;
+ }
+ fds = (struct pollfd *)malloc ((nfds) * sizeof (struct pollfd));
+ if (!fds)
+ error ("Can't allocate poll structures.");
+
+ do {
+ /* Call any expired timeouts, and then if there's
+ still a timeout registered, time out the select
+ call then. */
+ another:
+ if (timeouts) {
+ struct timeout *t;
+ if (timeouts -> when <= cur_time) {
+ t = timeouts;
+ timeouts = timeouts -> next;
+ (*(t -> func)) (t -> what);
+ t -> next = free_timeouts;
+ free_timeouts = t;
+ goto another;
+ }
+ /* Figure timeout in milliseconds, and check for
+ potential overflow. We assume that integers
+ are 32 bits, which is harmless if they're 64
+ bits - we'll just get extra timeouts in that
+ case. Lease times would have to be quite
+ long in order for a 32-bit integer to overflow,
+ anyway. */
+ to_msec = timeouts -> when - cur_time;
+ if (to_msec > 2147483)
+ to_msec = 2147483;
+ to_msec *= 1000;
+ } else
+ to_msec = -1;
+
+ /* Set up the descriptors to be polled. */
+ i = 0;
+ for (l = protocols; l; l = l -> next) {
+ fds [i].fd = l -> fd;
+ fds [i].events = POLLIN;
+ fds [i].revents = 0;
+ ++i;
+ }
+
+ /* Wait for a packet or a timeout... XXX */
+ count = poll (fds, nfds, to_msec);
+
+ /* Get the current time... */
+ GET_TIME (&cur_time);
+
+ /* Not likely to be transitory... */
+ if (count < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ else
+ error ("poll: %m");
+ }
+
+ i = 0;
+ for (l = protocols; l; l = l -> next) {
+ if ((fds [i].revents & POLLIN)) {
+ fds [i].revents = 0;
+ if (l -> handler)
+ (*(l -> handler)) (l);
+ if (interfaces_invalidated)
+ break;
+ }
+ ++i;
+ }
+ interfaces_invalidated = 0;
+ } while (1);
+}
+#else
+/* Wait for packets to come in using select(). When one does, call
+ receive_packet to receive the packet and possibly strip hardware
+ addressing information from it, and then call do_packet to try to
+ do something with it. */
+
+void dispatch ()
+{
+ fd_set r, w, x;
+ struct protocol *l;
+ int max = 0;
+ int count;
+ struct timeval tv, *tvp;
+
+ FD_ZERO (&w);
+ FD_ZERO (&x);
+
+ do {
+ /* Call any expired timeouts, and then if there's
+ still a timeout registered, time out the select
+ call then. */
+ another:
+ if (timeouts) {
+ struct timeout *t;
+ if (timeouts -> when <= cur_time) {
+ t = timeouts;
+ timeouts = timeouts -> next;
+ (*(t -> func)) (t -> what);
+ t -> next = free_timeouts;
+ free_timeouts = t;
+ goto another;
+ }
+ tv.tv_sec = timeouts -> when - cur_time;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ } else
+ tvp = (struct timeval *)0;
+
+ /* Set up the read mask. */
+ FD_ZERO (&r);
+
+ for (l = protocols; l; l = l -> next) {
+ FD_SET (l -> fd, &r);
+ if (l -> fd > max)
+ max = l -> fd;
+ }
+
+ /* Wait for a packet or a timeout... XXX */
+ count = select (max + 1, &r, &w, &x, tvp);
+
+ /* Get the current time... */
+ GET_TIME (&cur_time);
+
+ /* Not likely to be transitory... */
+ if (count < 0)
+ error ("select: %m");
+
+ for (l = protocols; l; l = l -> next) {
+ if (!FD_ISSET (l -> fd, &r))
+ continue;
+ if (l -> handler)
+ (*(l -> handler)) (l);
+ if (interfaces_invalidated)
+ break;
+ }
+ interfaces_invalidated = 0;
+ } while (1);
+}
+#endif /* USE_POLL */
+
+static void got_one (l)
+ struct protocol *l;
+{
+ struct sockaddr_in from;
+ struct hardware hfrom;
+ struct iaddr ifrom;
+ int result;
+ union {
+ unsigned char packbuf [4095]; /* Packet input buffer.
+ Must be as large as largest
+ possible MTU. */
+ struct dhcp_packet packet;
+ } u;
+ struct interface_info *ip = l -> local;
+
+ if ((result =
+ receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) {
+ warn ("receive_packet failed on %s: %m", ip -> name);
+ return;
+ }
+ if (result == 0)
+ return;
+
+ if (bootp_packet_handler) {
+ ifrom.len = 4;
+ memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
+
+ (*bootp_packet_handler) (ip, &u.packet, result,
+ from.sin_port, ifrom, &hfrom);
+ }
+}
+
+int locate_network (packet)
+ struct packet *packet;
+{
+ struct iaddr ia;
+
+ /* If this came through a gateway, find the corresponding subnet... */
+ if (packet -> raw -> giaddr.s_addr) {
+ struct subnet *subnet;
+ ia.len = 4;
+ memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
+ subnet = find_subnet (ia);
+ if (subnet)
+ packet -> shared_network = subnet -> shared_network;
+ else
+ packet -> shared_network = (struct shared_network *)0;
+ } else {
+ packet -> shared_network =
+ packet -> interface -> shared_network;
+ }
+ if (packet -> shared_network)
+ return 1;
+ return 0;
+}
+
+void add_timeout (when, where, what)
+ TIME when;
+ void (*where) PROTO ((void *));
+ void *what;
+{
+ struct timeout *t, *q;
+
+ /* See if this timeout supersedes an existing timeout. */
+ t = (struct timeout *)0;
+ for (q = timeouts; q; q = q -> next) {
+ if (q -> func == where && q -> what == what) {
+ if (t)
+ t -> next = q -> next;
+ else
+ timeouts = q -> next;
+ break;
+ }
+ t = q;
+ }
+
+ /* If we didn't supersede a timeout, allocate a timeout
+ structure now. */
+ if (!q) {
+ if (free_timeouts) {
+ q = free_timeouts;
+ free_timeouts = q -> next;
+ q -> func = where;
+ q -> what = what;
+ } else {
+ q = (struct timeout *)malloc (sizeof (struct timeout));
+ if (!q)
+ error ("Can't allocate timeout structure!");
+ q -> func = where;
+ q -> what = what;
+ }
+ }
+
+ q -> when = when;
+
+ /* Now sort this timeout into the timeout list. */
+
+ /* Beginning of list? */
+ if (!timeouts || timeouts -> when > q -> when) {
+ q -> next = timeouts;
+ timeouts = q;
+ return;
+ }
+
+ /* Middle of list? */
+ for (t = timeouts; t -> next; t = t -> next) {
+ if (t -> next -> when > q -> when) {
+ q -> next = t -> next;
+ t -> next = q;
+ return;
+ }
+ }
+
+ /* End of list. */
+ t -> next = q;
+ q -> next = (struct timeout *)0;
+}
+
+void cancel_timeout (where, what)
+ void (*where) PROTO ((void *));
+ void *what;
+{
+ struct timeout *t, *q;
+
+ /* Look for this timeout on the list, and unlink it if we find it. */
+ t = (struct timeout *)0;
+ for (q = timeouts; q; q = q -> next) {
+ if (q -> func == where && q -> what == what) {
+ if (t)
+ t -> next = q -> next;
+ else
+ timeouts = q -> next;
+ break;
+ }
+ t = q;
+ }
+
+ /* If we found the timeout, put it on the free list. */
+ if (q) {
+ q -> next = free_timeouts;
+ free_timeouts = q;
+ }
+}
+
+/* Add a protocol to the list of protocols... */
+void add_protocol (name, fd, handler, local)
+ char *name;
+ int fd;
+ void (*handler) PROTO ((struct protocol *));
+ void *local;
+{
+ struct protocol *p;
+
+ p = (struct protocol *)malloc (sizeof *p);
+ if (!p)
+ error ("can't allocate protocol struct for %s", name);
+
+ p -> fd = fd;
+ p -> handler = handler;
+ p -> local = local;
+
+ p -> next = protocols;
+ protocols = p;
+}
+
+void remove_protocol (proto)
+ struct protocol *proto;
+{
+ struct protocol *p, *next, *prev;
+
+ prev = (struct protocol *)0;
+ for (p = protocols; p; p = next) {
+ next = p -> next;
+ if (p == proto) {
+ if (prev)
+ prev -> next = p -> next;
+ else
+ protocols = p -> next;
+ free (p);
+ }
+ }
+}
diff --git a/contrib/isc-dhcp/common/errwarn.c b/contrib/isc-dhcp/common/errwarn.c
new file mode 100644
index 000000000000..078ae4172246
--- /dev/null
+++ b/contrib/isc-dhcp/common/errwarn.c
@@ -0,0 +1,391 @@
+/* errwarn.c
+
+ Errors and warnings... */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium.
+ * All Rights Reserved.
+ * Copyright (c) 1995 RadioMail Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of RadioMail Corporation, the Internet Software
+ * Consortium nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RADIOMAIL CORPORATION, THE INTERNET
+ * SOFTWARE CONSORTIUM AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL RADIOMAIL CORPORATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises. Further modifications have
+ * been made for the Internet Software Consortium under a contract
+ * with Vixie Laboratories.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: errwarn.c,v 1.15 1997/05/09 08:03:44 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include <errno.h>
+
+static void do_percentm PROTO ((char *obuf, char *ibuf));
+
+static char mbuf [1024];
+static char fbuf [1024];
+
+int warnings_occurred;
+
+/* Log an error message, then exit... */
+
+void error (ANSI_DECL(char *) fmt, VA_DOTDOTDOT)
+ KandR (char *fmt;)
+ va_dcl
+{
+ va_list list;
+ extern int logged_in;
+
+ do_percentm (fbuf, fmt);
+
+ VA_start (list, fmt);
+ vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+ va_end (list);
+
+#ifndef DEBUG
+ syslog (log_priority | LOG_ERR, mbuf);
+#endif
+
+ /* Also log it to stderr? */
+ if (log_perror) {
+ write (2, mbuf, strlen (mbuf));
+ write (2, "\n", 1);
+ }
+
+ syslog (LOG_CRIT, "exiting.");
+ if (log_perror) {
+ fprintf (stderr, "exiting.\n");
+ fflush (stderr);
+ }
+ cleanup ();
+ exit (1);
+}
+
+/* Log a warning message... */
+
+int warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+ KandR (char *fmt;)
+ va_dcl
+{
+ va_list list;
+
+ do_percentm (fbuf, fmt);
+
+ VA_start (list, fmt);
+ vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+ va_end (list);
+
+#ifndef DEBUG
+ syslog (log_priority | LOG_ERR, mbuf);
+#endif
+
+ if (log_perror) {
+ write (2, mbuf, strlen (mbuf));
+ write (2, "\n", 1);
+ }
+
+ return 0;
+}
+
+/* Log a note... */
+
+int note (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+ KandR (char *fmt;)
+ va_dcl
+{
+ va_list list;
+
+ do_percentm (fbuf, fmt);
+
+ VA_start (list, fmt);
+ vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+ va_end (list);
+
+#ifndef DEBUG
+ syslog (log_priority | LOG_INFO, mbuf);
+#endif
+
+ if (log_perror) {
+ write (2, mbuf, strlen (mbuf));
+ write (2, "\n", 1);
+ }
+
+ return 0;
+}
+
+/* Log a debug message... */
+
+int debug (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+ KandR (char *fmt;)
+ va_dcl
+{
+ va_list list;
+
+ do_percentm (fbuf, fmt);
+
+ VA_start (list, fmt);
+ vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+ va_end (list);
+
+#ifndef DEBUG
+ syslog (log_priority | LOG_DEBUG, mbuf);
+#endif
+
+ if (log_perror) {
+ write (2, mbuf, strlen (mbuf));
+ write (2, "\n", 1);
+ }
+
+ return 0;
+}
+
+/* Find %m in the input string and substitute an error message string. */
+
+static void do_percentm (obuf, ibuf)
+ char *obuf;
+ char *ibuf;
+{
+ char *s = ibuf;
+ char *p = obuf;
+ int infmt = 0;
+ char *m;
+
+ while (*s)
+ {
+ if (infmt)
+ {
+ if (*s == 'm')
+ {
+#ifndef __CYGWIN32__
+ m = strerror (errno);
+#else
+ m = pWSAError ();
+#endif
+ if (!m)
+ m = "<unknown error>";
+ strcpy (p - 1, m);
+ p += strlen (p);
+ ++s;
+ }
+ else
+ *p++ = *s++;
+ infmt = 0;
+ }
+ else
+ {
+ if (*s == '%')
+ infmt = 1;
+ *p++ = *s++;
+ }
+ }
+ *p = 0;
+}
+
+
+int parse_warn (ANSI_DECL (char *) fmt, VA_DOTDOTDOT)
+ KandR (char *fmt;)
+ va_dcl
+{
+ va_list list;
+ static char spaces [] = " ";
+
+ do_percentm (mbuf, fmt);
+#ifndef NO_SNPRINTF
+ snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
+ tlname, lexline, mbuf);
+#else
+ sprintf (fbuf, "%s line %d: %s",
+ tlname, lexline, mbuf);
+#endif
+
+ VA_start (list, fmt);
+ vsnprintf (mbuf, sizeof mbuf, fbuf, list);
+ va_end (list);
+
+#ifndef DEBUG
+ syslog (log_priority | LOG_ERR, mbuf);
+ syslog (log_priority | LOG_ERR, token_line);
+ if (lexline < 81)
+ syslog (log_priority | LOG_ERR,
+ "%s^", &spaces [sizeof spaces - lexchar]);
+#endif
+
+ if (log_perror) {
+ write (2, mbuf, strlen (mbuf));
+ write (2, "\n", 1);
+ write (2, token_line, strlen (token_line));
+ write (2, "\n", 1);
+ write (2, spaces, lexchar - 1);
+ write (2, "^\n", 2);
+ }
+
+ warnings_occurred = 1;
+
+ return 0;
+}
+
+#ifdef NO_STRERROR
+char *strerror (err)
+ int err;
+{
+ extern char *sys_errlist [];
+ extern int sys_nerr;
+ static char errbuf [128];
+
+ if (err < 0 || err >= sys_nerr) {
+ sprintf (errbuf, "Error %d", err);
+ return errbuf;
+ }
+ return sys_errlist [err];
+}
+#endif /* NO_STRERROR */
+
+#ifdef _WIN32
+char *pWSAError ()
+{
+ int err = WSAGetLastError ();
+
+ switch (err)
+ {
+ case WSAEACCES:
+ return "Permission denied";
+ case WSAEADDRINUSE:
+ return "Address already in use";
+ case WSAEADDRNOTAVAIL:
+ return "Cannot assign requested address";
+ case WSAEAFNOSUPPORT:
+ return "Address family not supported by protocol family";
+ case WSAEALREADY:
+ return "Operation already in progress";
+ case WSAECONNABORTED:
+ return "Software caused connection abort";
+ case WSAECONNREFUSED:
+ return "Connection refused";
+ case WSAECONNRESET:
+ return "Connection reset by peer";
+ case WSAEDESTADDRREQ:
+ return "Destination address required";
+ case WSAEFAULT:
+ return "Bad address";
+ case WSAEHOSTDOWN:
+ return "Host is down";
+ case WSAEHOSTUNREACH:
+ return "No route to host";
+ case WSAEINPROGRESS:
+ return "Operation now in progress";
+ case WSAEINTR:
+ return "Interrupted function call";
+ case WSAEINVAL:
+ return "Invalid argument";
+ case WSAEISCONN:
+ return "Socket is already connected";
+ case WSAEMFILE:
+ return "Too many open files";
+ case WSAEMSGSIZE:
+ return "Message too long";
+ case WSAENETDOWN:
+ return "Network is down";
+ case WSAENETRESET:
+ return "Network dropped connection on reset";
+ case WSAENETUNREACH:
+ return "Network is unreachable";
+ case WSAENOBUFS:
+ return "No buffer space available";
+ case WSAENOPROTOOPT:
+ return "Bad protocol option";
+ case WSAENOTCONN:
+ return "Socket is not connected";
+ case WSAENOTSOCK:
+ return "Socket operation on non-socket";
+ case WSAEOPNOTSUPP:
+ return "Operation not supported";
+ case WSAEPFNOSUPPORT:
+ return "Protocol family not supported";
+ case WSAEPROCLIM:
+ return "Too many processes";
+ case WSAEPROTONOSUPPORT:
+ return "Protocol not supported";
+ case WSAEPROTOTYPE:
+ return "Protocol wrong type for socket";
+ case WSAESHUTDOWN:
+ return "Cannot send after socket shutdown";
+ case WSAESOCKTNOSUPPORT:
+ return "Socket type not supported";
+ case WSAETIMEDOUT:
+ return "Connection timed out";
+ case WSAEWOULDBLOCK:
+ return "Resource temporarily unavailable";
+ case WSAHOST_NOT_FOUND:
+ return "Host not found";
+#if 0
+ case WSA_INVALID_HANDLE:
+ return "Specified event object handle is invalid";
+ case WSA_INVALID_PARAMETER:
+ return "One or more parameters are invalid";
+ case WSAINVALIDPROCTABLE:
+ return "Invalid procedure table from service provider";
+ case WSAINVALIDPROVIDER:
+ return "Invalid service provider version number";
+ case WSA_IO_PENDING:
+ return "Overlapped operations will complete later";
+ case WSA_IO_INCOMPLETE:
+ return "Overlapped I/O event object not in signaled state";
+ case WSA_NOT_ENOUGH_MEMORY:
+ return "Insufficient memory available";
+#endif
+ case WSANOTINITIALISED:
+ return "Successful WSAStartup not yet performer";
+ case WSANO_DATA:
+ return "Valid name, no data record of requested type";
+ case WSANO_RECOVERY:
+ return "This is a non-recoverable error";
+#if 0
+ case WSAPROVIDERFAILEDINIT:
+ return "Unable to initialize a service provider";
+ case WSASYSCALLFAILURE:
+ return "System call failure";
+#endif
+ case WSASYSNOTREADY:
+ return "Network subsystem is unavailable";
+ case WSATRY_AGAIN:
+ return "Non-authoritative host not found";
+ case WSAVERNOTSUPPORTED:
+ return "WINSOCK.DLL version out of range";
+ case WSAEDISCON:
+ return "Graceful shutdown in progress";
+#if 0
+ case WSA_OPERATION_ABORTED:
+ return "Overlapped operation aborted";
+#endif
+ }
+ return "Unknown WinSock error";
+}
+#endif /* _WIN32 */
diff --git a/contrib/isc-dhcp/common/hash.c b/contrib/isc-dhcp/common/hash.c
new file mode 100644
index 000000000000..8d362cb12b98
--- /dev/null
+++ b/contrib/isc-dhcp/common/hash.c
@@ -0,0 +1,175 @@
+/* hash.c
+
+ Routines for manipulating hash tables... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: hash.c,v 1.9.2.1 1998/06/25 21:11:29 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static INLINE int do_hash PROTO ((unsigned char *, int, int));
+
+struct hash_table *new_hash ()
+{
+ struct hash_table *rv = new_hash_table (DEFAULT_HASH_SIZE, "new_hash");
+ if (!rv)
+ return rv;
+ memset (&rv -> buckets [0], 0,
+ DEFAULT_HASH_SIZE * sizeof (struct hash_bucket *));
+ return rv;
+}
+
+static INLINE int do_hash (name, len, size)
+ unsigned char *name;
+ int len;
+ int size;
+{
+ register int accum = 0;
+ register unsigned char *s = name;
+ int i = len;
+ if (i) {
+ while (i--) {
+ /* Add the character in... */
+ accum += *s++;
+ /* Add carry back in... */
+ while (accum > 255) {
+ accum = (accum & 255) + (accum >> 8);
+ }
+ }
+ } else {
+ while (*s) {
+ /* Add the character in... */
+ accum += *s++;
+ /* Add carry back in... */
+ while (accum > 255) {
+ accum = (accum & 255) + (accum >> 8);
+ }
+ }
+ }
+ return accum % size;
+}
+
+void add_hash (table, name, len, pointer)
+ struct hash_table *table;
+ int len;
+ unsigned char *name;
+ unsigned char *pointer;
+{
+ int hashno;
+ struct hash_bucket *bp;
+
+ if (!table)
+ return;
+
+ hashno = do_hash (name, len, table -> hash_count);
+ bp = new_hash_bucket ("add_hash");
+
+ if (!bp) {
+ warn ("Can't add %s to hash table.", name);
+ return;
+ }
+ bp -> name = name;
+ bp -> value = pointer;
+ bp -> next = table -> buckets [hashno];
+ bp -> len = len;
+ table -> buckets [hashno] = bp;
+}
+
+void delete_hash_entry (table, name, len)
+ struct hash_table *table;
+ int len;
+ unsigned char *name;
+{
+ int hashno;
+ struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
+
+ if (!table)
+ return;
+
+ hashno = do_hash (name, len, table -> hash_count);
+
+ /* Go through the list looking for an entry that matches;
+ if we find it, delete it. */
+ for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
+ if ((!bp -> len &&
+ !strcmp ((char *)bp -> name, (char *)name)) ||
+ (bp -> len == len &&
+ !memcmp (bp -> name, name, len))) {
+ if (pbp) {
+ pbp -> next = bp -> next;
+ } else {
+ table -> buckets [hashno] = bp -> next;
+ }
+ free_hash_bucket (bp, "delete_hash_entry");
+ break;
+ }
+ pbp = bp; /* jwg, 9/6/96 - nice catch! */
+ }
+}
+
+unsigned char *hash_lookup (table, name, len)
+ struct hash_table *table;
+ unsigned char *name;
+ int len;
+{
+ int hashno;
+ struct hash_bucket *bp;
+
+ if (!table)
+ return (unsigned char *)0;
+ hashno = do_hash (name, len, table -> hash_count);
+
+ if (len) {
+ for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
+ if (len == bp -> len
+ && !memcmp (bp -> name, name, len))
+ return bp -> value;
+ }
+ } else {
+ for (bp = table -> buckets [hashno]; bp; bp = bp -> next)
+ if (!strcmp ((char *)bp -> name, (char *)name))
+ return bp -> value;
+ }
+ return (unsigned char *)0;
+}
+
diff --git a/contrib/isc-dhcp/common/icmp.c b/contrib/isc-dhcp/common/icmp.c
new file mode 100644
index 000000000000..fb6cfad970df
--- /dev/null
+++ b/contrib/isc-dhcp/common/icmp.c
@@ -0,0 +1,177 @@
+/* icmp.c
+
+ ICMP Protocol engine - for sending out pings and receiving
+ responses. */
+
+/*
+ * Copyright (c) 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: icmp.c,v 1.7.2.1 1998/06/25 21:11:29 mellon Exp $ Copyright (c) 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "netinet/ip.h"
+#include "netinet/ip_icmp.h"
+
+static int icmp_protocol_initialized;
+static int icmp_protocol_fd;
+
+/* Initialize the ICMP protocol. */
+
+void icmp_startup (routep, handler)
+ int routep;
+ void (*handler) PROTO ((struct iaddr, u_int8_t *, int));
+{
+ struct protoent *proto;
+ int protocol = 1;
+ struct sockaddr_in from;
+ int fd;
+ int state;
+
+ /* Only initialize icmp once. */
+ if (icmp_protocol_initialized)
+ error ("attempted to reinitialize icmp protocol");
+ icmp_protocol_initialized = 1;
+
+ /* Get the protocol number (should be 1). */
+ proto = getprotobyname ("icmp");
+ if (proto)
+ protocol = proto -> p_proto;
+
+ /* Get a raw socket for the ICMP protocol. */
+ icmp_protocol_fd = socket (AF_INET, SOCK_RAW, protocol);
+ if (icmp_protocol_fd < 0)
+ error ("unable to create icmp socket: %m");
+
+ /* Make sure it does routing... */
+ state = 0;
+ if (setsockopt (icmp_protocol_fd, SOL_SOCKET, SO_DONTROUTE,
+ (char *)&state, sizeof state) < 0)
+ error ("Unable to disable SO_DONTROUTE on ICMP socket: %m");
+
+ add_protocol ("icmp", icmp_protocol_fd, icmp_echoreply,
+ (void *)handler);
+}
+
+int icmp_echorequest (addr)
+ struct iaddr *addr;
+{
+ struct sockaddr_in to;
+ struct icmp icmp;
+ int status;
+
+ if (!icmp_protocol_initialized)
+ error ("attempt to use ICMP protocol before initialization.");
+
+#ifdef HAVE_SA_LEN
+ to.sin_len = sizeof to;
+#endif
+ to.sin_family = AF_INET;
+ to.sin_port = 0; /* unused. */
+ memcpy (&to.sin_addr, addr -> iabuf, sizeof to.sin_addr); /* XXX */
+
+ icmp.icmp_type = ICMP_ECHO;
+ icmp.icmp_code = 0;
+ icmp.icmp_cksum = 0;
+ icmp.icmp_seq = 0;
+#ifdef PTRSIZE_64BIT
+ icmp.icmp_id = (((u_int32_t)(u_int64_t)addr) ^
+ (u_int32_t)(((u_int64_t)addr) >> 32));
+#else
+ icmp.icmp_id = (u_int32_t)addr;
+#endif
+
+ icmp.icmp_cksum = wrapsum (checksum ((unsigned char *)&icmp,
+ sizeof icmp, 0));
+
+ /* Send the ICMP packet... */
+ status = sendto (icmp_protocol_fd, (char *)&icmp, sizeof icmp, 0,
+ (struct sockaddr *)&to, sizeof to);
+ if (status < 0)
+ warn ("icmp_echorequest %s: %m", inet_ntoa(to.sin_addr));
+
+ if (status != sizeof icmp)
+ return 0;
+ return 1;
+}
+
+void icmp_echoreply (protocol)
+ struct protocol *protocol;
+{
+ struct icmp *icfrom;
+ struct sockaddr_in from;
+ u_int8_t icbuf [1500];
+ int status;
+ int len;
+ struct iaddr ia;
+ void (*handler) PROTO ((struct iaddr, u_int8_t *, int));
+
+ len = sizeof from;
+ status = recvfrom (protocol -> fd, (char *)icbuf, sizeof icbuf, 0,
+ (struct sockaddr *)&from, &len);
+ if (status < 0) {
+ warn ("icmp_echoreply: %m");
+ return;
+ }
+
+ /* Probably not for us. */
+ if (status < (sizeof (struct ip)) + (sizeof *icfrom)) {
+ return;
+ }
+
+ len = status - sizeof (struct ip);
+ icfrom = (struct icmp *)(icbuf + sizeof (struct ip));
+
+ /* Silently discard ICMP packets that aren't echoreplies. */
+ if (icfrom -> icmp_type != ICMP_ECHOREPLY) {
+ return;
+ }
+
+ /* If we were given a second-stage handler, call it. */
+ if (protocol -> local) {
+ handler = ((void (*) PROTO ((struct iaddr,
+ u_int8_t *, int)))
+ protocol -> local);
+ memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr);
+ ia.len = sizeof from.sin_addr;
+
+ (*handler) (ia, icbuf, len);
+ }
+}
diff --git a/contrib/isc-dhcp/common/inet.c b/contrib/isc-dhcp/common/inet.c
new file mode 100644
index 000000000000..b7c4ba438480
--- /dev/null
+++ b/contrib/isc-dhcp/common/inet.c
@@ -0,0 +1,178 @@
+/* inet.c
+
+ Subroutines to manipulate internet addresses in a safely portable
+ way... */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include "dhcpd.h"
+
+/* Return just the network number of an internet address... */
+
+struct iaddr subnet_number (addr, mask)
+ struct iaddr addr;
+ struct iaddr mask;
+{
+ int i;
+ struct iaddr rv;
+
+ rv.len = 0;
+
+ /* Both addresses must have the same length... */
+ if (addr.len != mask.len)
+ return rv;
+
+ rv.len = addr.len;
+ for (i = 0; i < rv.len; i++)
+ rv.iabuf [i] = addr.iabuf [i] & mask.iabuf [i];
+ return rv;
+}
+
+/* Combine a network number and a integer to produce an internet address.
+ This won't work for subnets with more than 32 bits of host address, but
+ maybe this isn't a problem. */
+
+struct iaddr ip_addr (subnet, mask, host_address)
+ struct iaddr subnet;
+ struct iaddr mask;
+ u_int32_t host_address;
+{
+ int i, j, k;
+ u_int32_t swaddr;
+ struct iaddr rv;
+ unsigned char habuf [sizeof swaddr];
+
+ swaddr = htonl (host_address);
+ memcpy (habuf, &swaddr, sizeof swaddr);
+
+ /* Combine the subnet address and the host address. If
+ the host address is bigger than can fit in the subnet,
+ return a zero-length iaddr structure. */
+ rv = subnet;
+ j = rv.len - sizeof habuf;
+ for (i = sizeof habuf - 1; i >= 0; i--) {
+ if (mask.iabuf [i + j]) {
+ if (habuf [i] > (mask.iabuf [i + j] ^ 0xFF)) {
+ rv.len = 0;
+ return rv;
+ }
+ for (k = i - 1; k >= 0; k--) {
+ if (habuf [k]) {
+ rv.len = 0;
+ return rv;
+ }
+ }
+ rv.iabuf [i + j] |= habuf [i];
+ break;
+ } else
+ rv.iabuf [i + j] = habuf [i];
+ }
+
+ return rv;
+}
+
+/* Given a subnet number and netmask, return the address on that subnet
+ for which the host portion of the address is all ones (the standard
+ broadcast address). */
+
+struct iaddr broadcast_addr (subnet, mask)
+ struct iaddr subnet;
+ struct iaddr mask;
+{
+ int i, j, k;
+ struct iaddr rv;
+
+ if (subnet.len != mask.len) {
+ rv.len = 0;
+ return rv;
+ }
+
+ for (i = 0; i < subnet.len; i++) {
+ rv.iabuf [i] = subnet.iabuf [i] | (~mask.iabuf [i] & 255);
+ }
+ rv.len = subnet.len;
+
+ return rv;
+}
+
+u_int32_t host_addr (addr, mask)
+ struct iaddr addr;
+ struct iaddr mask;
+{
+ int i;
+ u_int32_t swaddr;
+ struct iaddr rv;
+
+ rv.len = 0;
+
+ /* Mask out the network bits... */
+ rv.len = addr.len;
+ for (i = 0; i < rv.len; i++)
+ rv.iabuf [i] = addr.iabuf [i] & ~mask.iabuf [i];
+
+ /* Copy out up to 32 bits... */
+ memcpy (&swaddr, &rv.iabuf [rv.len - sizeof swaddr], sizeof swaddr);
+
+ /* Swap it and return it. */
+ return ntohl (swaddr);
+}
+
+int addr_eq (addr1, addr2)
+ struct iaddr addr1, addr2;
+{
+ if (addr1.len != addr2.len)
+ return 0;
+ return memcmp (addr1.iabuf, addr2.iabuf, addr1.len) == 0;
+}
+
+char *piaddr (addr)
+ struct iaddr addr;
+{
+ static char pbuf [4 * 16];
+ char *s = pbuf;
+ int i;
+
+ if (addr.len == 0) {
+ strcpy (s, "<null address>");
+ }
+ for (i = 0; i < addr.len; i++) {
+ sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]);
+ s += strlen (s);
+ }
+ return pbuf;
+}
diff --git a/contrib/isc-dhcp/common/inet_addr.c b/contrib/isc-dhcp/common/inet_addr.c
new file mode 100644
index 000000000000..b00a72c4674f
--- /dev/null
+++ b/contrib/isc-dhcp/common/inet_addr.c
@@ -0,0 +1,150 @@
+/* $NetBSD: inet_addr.c,v 1.6 1996/02/02 15:22:23 mrg Exp $ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+#else
+static char rcsid[] = "$NetBSD: inet_addr.c,v 1.6 1996/02/02 15:22:23 mrg Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#ifndef lint
+static char copyright[] =
+"$Id: inet_addr.c,v 1.2.2.1 1998/06/26 20:51:35 mellon Exp $ Copyright (c) 1983, 1990, 1993 The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+#ifdef NEED_INET_ATON
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(cp, addr)
+ const char *cp;
+ struct in_addr *addr;
+{
+ register u_long val;
+ register int base, n;
+ register char c;
+ u_int parts[4];
+ register u_int *pp = parts;
+
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, other=decimal.
+ */
+ val = 0; base = 10;
+ if (*cp == '0') {
+ if (*++cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ else
+ base = 8;
+ }
+ while ((c = *cp) != '\0') {
+ if (isascii(c) && isdigit(c)) {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) +
+ (c + 10 - (islower(c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return (0);
+ *pp++ = val, cp++;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (*cp && (!isascii(*cp) || !isspace(*cp)))
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+#endif
diff --git a/contrib/isc-dhcp/common/memory.c b/contrib/isc-dhcp/common/memory.c
new file mode 100644
index 000000000000..59cbe5dafc01
--- /dev/null
+++ b/contrib/isc-dhcp/common/memory.c
@@ -0,0 +1,911 @@
+/* memory.c
+
+ Memory-resident database... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: memory.c,v 1.35.2.2 1998/06/25 21:11:30 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static struct subnet *subnets;
+static struct shared_network *shared_networks;
+static struct hash_table *host_hw_addr_hash;
+static struct hash_table *host_uid_hash;
+static struct hash_table *lease_uid_hash;
+static struct hash_table *lease_ip_addr_hash;
+static struct hash_table *lease_hw_addr_hash;
+static struct lease *dangling_leases;
+
+static struct hash_table *vendor_class_hash;
+static struct hash_table *user_class_hash;
+
+void enter_host (hd)
+ struct host_decl *hd;
+{
+ struct host_decl *hp = (struct host_decl *)0;
+ struct host_decl *np = (struct host_decl *)0;
+
+ hd -> n_ipaddr = (struct host_decl *)0;
+
+ if (hd -> interface.hlen) {
+ if (!host_hw_addr_hash)
+ host_hw_addr_hash = new_hash ();
+ else
+ hp = (struct host_decl *)
+ hash_lookup (host_hw_addr_hash,
+ hd -> interface.haddr,
+ hd -> interface.hlen);
+
+ /* If there isn't already a host decl matching this
+ address, add it to the hash table. */
+ if (!hp)
+ add_hash (host_hw_addr_hash,
+ hd -> interface.haddr, hd -> interface.hlen,
+ (unsigned char *)hd);
+ }
+
+ /* If there was already a host declaration for this hardware
+ address, add this one to the end of the list. */
+
+ if (hp) {
+ for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
+ ;
+ np -> n_ipaddr = hd;
+ }
+
+ if (hd -> group -> options [DHO_DHCP_CLIENT_IDENTIFIER]) {
+ if (!tree_evaluate (hd -> group -> options
+ [DHO_DHCP_CLIENT_IDENTIFIER]))
+ return;
+
+ /* If there's no uid hash, make one; otherwise, see if
+ there's already an entry in the hash for this host. */
+ if (!host_uid_hash) {
+ host_uid_hash = new_hash ();
+ hp = (struct host_decl *)0;
+ } else
+ hp = (struct host_decl *) hash_lookup
+ (host_uid_hash,
+ hd -> group -> options
+ [DHO_DHCP_CLIENT_IDENTIFIER] -> value,
+ hd -> group -> options
+ [DHO_DHCP_CLIENT_IDENTIFIER] -> len);
+
+ /* If there's already a host declaration for this
+ client identifier, add this one to the end of the
+ list. Otherwise, add it to the hash table. */
+ if (hp) {
+ /* Don't link it in twice... */
+ if (!np) {
+ for (np = hp; np -> n_ipaddr;
+ np = np -> n_ipaddr)
+ ;
+ np -> n_ipaddr = hd;
+ }
+ } else {
+ add_hash (host_uid_hash,
+ hd -> group -> options
+ [DHO_DHCP_CLIENT_IDENTIFIER] -> value,
+ hd -> group -> options
+ [DHO_DHCP_CLIENT_IDENTIFIER] -> len,
+ (unsigned char *)hd);
+ }
+ }
+}
+
+struct host_decl *find_hosts_by_haddr (htype, haddr, hlen)
+ int htype;
+ unsigned char *haddr;
+ int hlen;
+{
+ struct host_decl *foo;
+
+ foo = (struct host_decl *)hash_lookup (host_hw_addr_hash,
+ haddr, hlen);
+ return foo;
+}
+
+struct host_decl *find_hosts_by_uid (data, len)
+ unsigned char *data;
+ int len;
+{
+ struct host_decl *foo;
+
+ foo = (struct host_decl *)hash_lookup (host_uid_hash, data, len);
+ return foo;
+}
+
+/* More than one host_decl can be returned by find_hosts_by_haddr or
+ find_hosts_by_uid, and each host_decl can have multiple addresses.
+ Loop through the list of hosts, and then for each host, through the
+ list of addresses, looking for an address that's in the same shared
+ network as the one specified. Store the matching address through
+ the addr pointer, update the host pointer to point at the host_decl
+ that matched, and return the subnet that matched. */
+
+struct subnet *find_host_for_network (host, addr, share)
+ struct host_decl **host;
+ struct iaddr *addr;
+ struct shared_network *share;
+{
+ int i;
+ struct subnet *subnet;
+ struct iaddr ip_address;
+ struct host_decl *hp;
+
+ for (hp = *host; hp; hp = hp -> n_ipaddr) {
+ if (!hp -> fixed_addr || !tree_evaluate (hp -> fixed_addr))
+ continue;
+ for (i = 0; i < hp -> fixed_addr -> len; i += 4) {
+ ip_address.len = 4;
+ memcpy (ip_address.iabuf,
+ hp -> fixed_addr -> value + i, 4);
+ subnet = find_grouped_subnet (share, ip_address);
+ if (subnet) {
+ *addr = ip_address;
+ *host = hp;
+ return subnet;
+ }
+ }
+ }
+ return (struct subnet *)0;
+}
+
+void new_address_range (low, high, subnet, dynamic)
+ struct iaddr low, high;
+ struct subnet *subnet;
+ int dynamic;
+{
+ struct lease *address_range, *lp, *plp;
+ struct iaddr net;
+ int min, max, i;
+ char lowbuf [16], highbuf [16], netbuf [16];
+ struct shared_network *share = subnet -> shared_network;
+ struct hostent *h;
+ struct in_addr ia;
+
+ /* All subnets should have attached shared network structures. */
+ if (!share) {
+ strcpy (netbuf, piaddr (subnet -> net));
+ error ("No shared network for network %s (%s)",
+ netbuf, piaddr (subnet -> netmask));
+ }
+
+ /* Initialize the hash table if it hasn't been done yet. */
+ if (!lease_uid_hash)
+ lease_uid_hash = new_hash ();
+ if (!lease_ip_addr_hash)
+ lease_ip_addr_hash = new_hash ();
+ if (!lease_hw_addr_hash)
+ lease_hw_addr_hash = new_hash ();
+
+ /* Make sure that high and low addresses are in same subnet. */
+ net = subnet_number (low, subnet -> netmask);
+ if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
+ strcpy (lowbuf, piaddr (low));
+ strcpy (highbuf, piaddr (high));
+ strcpy (netbuf, piaddr (subnet -> netmask));
+ error ("Address range %s to %s, netmask %s spans %s!",
+ lowbuf, highbuf, netbuf, "multiple subnets");
+ }
+
+ /* Make sure that the addresses are on the correct subnet. */
+ if (!addr_eq (net, subnet -> net)) {
+ strcpy (lowbuf, piaddr (low));
+ strcpy (highbuf, piaddr (high));
+ strcpy (netbuf, piaddr (subnet -> netmask));
+ error ("Address range %s to %s not on net %s/%s!",
+ lowbuf, highbuf, piaddr (subnet -> net), netbuf);
+ }
+
+ /* Get the high and low host addresses... */
+ max = host_addr (high, subnet -> netmask);
+ min = host_addr (low, subnet -> netmask);
+
+ /* Allow range to be specified high-to-low as well as low-to-high. */
+ if (min > max) {
+ max = min;
+ min = host_addr (high, subnet -> netmask);
+ }
+
+ /* Get a lease structure for each address in the range. */
+ address_range = new_leases (max - min + 1, "new_address_range");
+ if (!address_range) {
+ strcpy (lowbuf, piaddr (low));
+ strcpy (highbuf, piaddr (high));
+ error ("No memory for address range %s-%s.", lowbuf, highbuf);
+ }
+ memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
+
+ /* Fill in the last lease if it hasn't been already... */
+ if (!share -> last_lease) {
+ share -> last_lease = &address_range [0];
+ }
+
+ /* Fill out the lease structures with some minimal information. */
+ for (i = 0; i < max - min + 1; i++) {
+ address_range [i].ip_addr =
+ ip_addr (subnet -> net, subnet -> netmask, i + min);
+ address_range [i].starts =
+ address_range [i].timestamp = MIN_TIME;
+ address_range [i].ends = MIN_TIME;
+ address_range [i].subnet = subnet;
+ address_range [i].shared_network = share;
+ address_range [i].flags = dynamic ? DYNAMIC_BOOTP_OK : 0;
+
+ memcpy (&ia, address_range [i].ip_addr.iabuf, 4);
+
+ if (subnet -> group -> get_lease_hostnames) {
+ h = gethostbyaddr ((char *)&ia, sizeof ia, AF_INET);
+ if (!h)
+ warn ("No hostname for %s", inet_ntoa (ia));
+ else {
+ address_range [i].hostname =
+ malloc (strlen (h -> h_name) + 1);
+ if (!address_range [i].hostname)
+ error ("no memory for hostname %s.",
+ h -> h_name);
+ strcpy (address_range [i].hostname,
+ h -> h_name);
+ }
+ }
+
+ /* Link this entry into the list. */
+ address_range [i].next = share -> leases;
+ address_range [i].prev = (struct lease *)0;
+ share -> leases = &address_range [i];
+ if (address_range [i].next)
+ address_range [i].next -> prev = share -> leases;
+ add_hash (lease_ip_addr_hash,
+ address_range [i].ip_addr.iabuf,
+ address_range [i].ip_addr.len,
+ (unsigned char *)&address_range [i]);
+ }
+
+ /* Find out if any dangling leases are in range... */
+ plp = (struct lease *)0;
+ for (lp = dangling_leases; lp; lp = lp -> next) {
+ struct iaddr lnet;
+ int lhost;
+
+ lnet = subnet_number (lp -> ip_addr, subnet -> netmask);
+ lhost = host_addr (lp -> ip_addr, subnet -> netmask);
+
+ /* If it's in range, fill in the real lease structure with
+ the dangling lease's values, and remove the lease from
+ the list of dangling leases. */
+ if (addr_eq (lnet, subnet -> net) &&
+ lhost >= i && lhost <= max) {
+ if (plp) {
+ plp -> next = lp -> next;
+ } else {
+ dangling_leases = lp -> next;
+ }
+ lp -> next = (struct lease *)0;
+ address_range [lhost - i].hostname = lp -> hostname;
+ address_range [lhost - i].client_hostname =
+ lp -> client_hostname;
+ supersede_lease (&address_range [lhost - i], lp, 0);
+ free_lease (lp, "new_address_range");
+ } else
+ plp = lp;
+ }
+}
+
+struct subnet *find_subnet (addr)
+ struct iaddr addr;
+{
+ struct subnet *rv;
+
+ for (rv = subnets; rv; rv = rv -> next_subnet) {
+ if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
+ return rv;
+ }
+ return (struct subnet *)0;
+}
+
+struct subnet *find_grouped_subnet (share, addr)
+ struct shared_network *share;
+ struct iaddr addr;
+{
+ struct subnet *rv;
+
+ for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
+ if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
+ return rv;
+ }
+ return (struct subnet *)0;
+}
+
+/* Enter a new subnet into the subnet list. */
+
+void enter_subnet (subnet)
+ struct subnet *subnet;
+{
+ struct subnet *scan;
+
+ /* Check for duplicates... */
+ for (scan = subnets; scan; scan = scan -> next_subnet) {
+ if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
+ scan -> net) ||
+ addr_eq (subnet_number (scan -> net, subnet -> netmask),
+ subnet -> net)) {
+ char n1buf [16];
+ int i, j;
+ for (i = 0; i < 32; i++)
+ if (subnet -> netmask.iabuf [3 - (i >> 3)]
+ & (1 << (i & 7)))
+ break;
+ for (j = 0; j < 32; j++)
+ if (scan -> netmask.iabuf [3 - (j >> 3)]
+ & (1 << (j & 7)))
+ break;
+ strcpy (n1buf, piaddr (subnet -> net));
+ error ("subnet %s/%d conflicts with subnet %s/%d",
+ n1buf, i, piaddr (scan -> net), j);
+ }
+ }
+
+ /* XXX Sort the nets into a balanced tree to make searching quicker. */
+ subnet -> next_subnet = subnets;
+ subnets = subnet;
+}
+
+/* Enter a new shared network into the shared network list. */
+
+void enter_shared_network (share)
+ struct shared_network *share;
+{
+ /* XXX Sort the nets into a balanced tree to make searching quicker. */
+ share -> next = shared_networks;
+ shared_networks = share;
+}
+
+/* Enter a lease into the system. This is called by the parser each
+ time it reads in a new lease. If the subnet for that lease has
+ already been read in (usually the case), just update that lease;
+ otherwise, allocate temporary storage for the lease and keep it around
+ until we're done reading in the config file. */
+
+void enter_lease (lease)
+ struct lease *lease;
+{
+ struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
+
+ /* If we don't have a place for this lease yet, save it for
+ later. */
+ if (!comp) {
+ comp = new_lease ("enter_lease");
+ if (!comp) {
+ error ("No memory for lease %s\n",
+ piaddr (lease -> ip_addr));
+ }
+ *comp = *lease;
+ comp -> next = dangling_leases;
+ comp -> prev = (struct lease *)0;
+ dangling_leases = comp;
+ } else {
+ /* Record the hostname information in the lease. */
+ comp -> hostname = lease -> hostname;
+ comp -> client_hostname = lease -> client_hostname;
+ supersede_lease (comp, lease, 0);
+ }
+}
+
+/* Replace the data in an existing lease with the data in a new lease;
+ adjust hash tables to suit, and insertion sort the lease into the
+ list of leases by expiry time so that we can always find the oldest
+ lease. */
+
+int supersede_lease (comp, lease, commit)
+ struct lease *comp, *lease;
+ int commit;
+{
+ int enter_uid = 0;
+ int enter_hwaddr = 0;
+ struct lease *lp;
+
+ /* Static leases are not currently kept in the database... */
+ if (lease -> flags & STATIC_LEASE)
+ return 1;
+
+ /* If the existing lease hasn't expired and has a different
+ unique identifier or, if it doesn't have a unique
+ identifier, a different hardware address, then the two
+ leases are in conflict. If the existing lease has a uid
+ and the new one doesn't, but they both have the same
+ hardware address, and dynamic bootp is allowed on this
+ lease, then we allow that, in case a dynamic BOOTP lease is
+ requested *after* a DHCP lease has been assigned. */
+
+ if (!(lease -> flags & ABANDONED_LEASE) &&
+ comp -> ends > cur_time &&
+ (((comp -> uid && lease -> uid) &&
+ (comp -> uid_len != lease -> uid_len ||
+ memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
+ (!comp -> uid &&
+ ((comp -> hardware_addr.htype !=
+ lease -> hardware_addr.htype) ||
+ (comp -> hardware_addr.hlen !=
+ lease -> hardware_addr.hlen) ||
+ memcmp (comp -> hardware_addr.haddr,
+ lease -> hardware_addr.haddr,
+ comp -> hardware_addr.hlen))))) {
+ warn ("Lease conflict at %s",
+ piaddr (comp -> ip_addr));
+ return 0;
+ } else {
+ /* If there's a Unique ID, dissociate it from the hash
+ table and free it if necessary. */
+ if (comp -> uid) {
+ uid_hash_delete (comp);
+ enter_uid = 1;
+ if (comp -> uid != &comp -> uid_buf [0]) {
+ free (comp -> uid);
+ comp -> uid_max = 0;
+ comp -> uid_len = 0;
+ }
+ comp -> uid = (unsigned char *)0;
+ } else
+ enter_uid = 1;
+
+ if (comp -> hardware_addr.htype &&
+ ((comp -> hardware_addr.hlen !=
+ lease -> hardware_addr.hlen) ||
+ (comp -> hardware_addr.htype !=
+ lease -> hardware_addr.htype) ||
+ memcmp (comp -> hardware_addr.haddr,
+ lease -> hardware_addr.haddr,
+ comp -> hardware_addr.hlen))) {
+ hw_hash_delete (comp);
+ enter_hwaddr = 1;
+ } else if (!comp -> hardware_addr.htype)
+ enter_hwaddr = 1;
+
+ /* Copy the data files, but not the linkages. */
+ comp -> starts = lease -> starts;
+ comp -> timestamp = lease -> timestamp;
+ if (lease -> uid) {
+ if (lease -> uid_len < sizeof (lease -> uid_buf)) {
+ memcpy (comp -> uid_buf,
+ lease -> uid, lease -> uid_len);
+ comp -> uid = &comp -> uid_buf [0];
+ comp -> uid_max = sizeof comp -> uid_buf;
+ } else if (lease -> uid != &lease -> uid_buf [0]) {
+ comp -> uid = lease -> uid;
+ comp -> uid_max = lease -> uid_max;
+ lease -> uid = (unsigned char *)0;
+ lease -> uid_max = 0;
+ } else {
+ error ("corrupt lease uid."); /* XXX */
+ }
+ } else {
+ comp -> uid = (unsigned char *)0;
+ comp -> uid_max = 0;
+ }
+ comp -> uid_len = lease -> uid_len;
+ comp -> host = lease -> host;
+ comp -> hardware_addr = lease -> hardware_addr;
+ comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
+ (comp -> flags & ~EPHEMERAL_FLAGS));
+
+ /* Record the lease in the uid hash if necessary. */
+ if (enter_uid && lease -> uid) {
+ uid_hash_add (comp);
+ }
+
+ /* Record it in the hardware address hash if necessary. */
+ if (enter_hwaddr && lease -> hardware_addr.htype) {
+ hw_hash_add (comp);
+ }
+
+ /* Remove the lease from its current place in the
+ timeout sequence. */
+ if (comp -> prev) {
+ comp -> prev -> next = comp -> next;
+ } else {
+ comp -> shared_network -> leases = comp -> next;
+ }
+ if (comp -> next) {
+ comp -> next -> prev = comp -> prev;
+ }
+ if (comp -> shared_network -> last_lease == comp) {
+ comp -> shared_network -> last_lease = comp -> prev;
+ }
+
+ /* Find the last insertion point... */
+ if (comp == comp -> shared_network -> insertion_point ||
+ !comp -> shared_network -> insertion_point) {
+ lp = comp -> shared_network -> leases;
+ } else {
+ lp = comp -> shared_network -> insertion_point;
+ }
+
+ if (!lp) {
+ /* Nothing on the list yet? Just make comp the
+ head of the list. */
+ comp -> shared_network -> leases = comp;
+ comp -> shared_network -> last_lease = comp;
+ } else if (lp -> ends > lease -> ends) {
+ /* Skip down the list until we run out of list
+ or find a place for comp. */
+ while (lp -> next && lp -> ends > lease -> ends) {
+ lp = lp -> next;
+ }
+ if (lp -> ends > lease -> ends) {
+ /* If we ran out of list, put comp
+ at the end. */
+ lp -> next = comp;
+ comp -> prev = lp;
+ comp -> next = (struct lease *)0;
+ comp -> shared_network -> last_lease = comp;
+ } else {
+ /* If we didn't, put it between lp and
+ the previous item on the list. */
+ if ((comp -> prev = lp -> prev))
+ comp -> prev -> next = comp;
+ comp -> next = lp;
+ lp -> prev = comp;
+ }
+ } else {
+ /* Skip up the list until we run out of list
+ or find a place for comp. */
+ while (lp -> prev && lp -> ends < lease -> ends) {
+ lp = lp -> prev;
+ }
+ if (lp -> ends < lease -> ends) {
+ /* If we ran out of list, put comp
+ at the beginning. */
+ lp -> prev = comp;
+ comp -> next = lp;
+ comp -> prev = (struct lease *)0;
+ comp -> shared_network -> leases = comp;
+ } else {
+ /* If we didn't, put it between lp and
+ the next item on the list. */
+ if ((comp -> next = lp -> next))
+ comp -> next -> prev = comp;
+ comp -> prev = lp;
+ lp -> next = comp;
+ }
+ }
+ comp -> shared_network -> insertion_point = comp;
+ comp -> ends = lease -> ends;
+ }
+
+ /* Return zero if we didn't commit the lease to permanent storage;
+ nonzero if we did. */
+ return commit && write_lease (comp) && commit_leases ();
+}
+
+/* Release the specified lease and re-hash it as appropriate. */
+
+void release_lease (lease)
+ struct lease *lease;
+{
+ struct lease lt;
+
+ lt = *lease;
+ lt.ends = cur_time;
+ supersede_lease (lease, &lt, 1);
+}
+
+/* Abandon the specified lease (set its timeout to infinity and its
+ particulars to zero, and re-hash it as appropriate. */
+
+void abandon_lease (lease, message)
+ struct lease *lease;
+ char *message;
+{
+ struct lease lt;
+
+ lease -> flags |= ABANDONED_LEASE;
+ lt = *lease;
+ lt.ends = cur_time;
+ warn ("Abandoning IP address %s: %s",
+ piaddr (lease -> ip_addr), message);
+ lt.hardware_addr.htype = 0;
+ lt.hardware_addr.hlen = 0;
+ lt.uid = (unsigned char *)0;
+ lt.uid_len = 0;
+ supersede_lease (lease, &lt, 1);
+}
+
+/* Locate the lease associated with a given IP address... */
+
+struct lease *find_lease_by_ip_addr (addr)
+ struct iaddr addr;
+{
+ struct lease *lease = (struct lease *)hash_lookup (lease_ip_addr_hash,
+ addr.iabuf,
+ addr.len);
+ return lease;
+}
+
+struct lease *find_lease_by_uid (uid, len)
+ unsigned char *uid;
+ int len;
+{
+ struct lease *lease = (struct lease *)hash_lookup (lease_uid_hash,
+ uid, len);
+ return lease;
+}
+
+struct lease *find_lease_by_hw_addr (hwaddr, hwlen)
+ unsigned char *hwaddr;
+ int hwlen;
+{
+ struct lease *lease = (struct lease *)hash_lookup (lease_hw_addr_hash,
+ hwaddr, hwlen);
+ return lease;
+}
+
+/* Add the specified lease to the uid hash. */
+
+void uid_hash_add (lease)
+ struct lease *lease;
+{
+ struct lease *head =
+ find_lease_by_uid (lease -> uid, lease -> uid_len);
+ struct lease *scan;
+
+#ifdef DEBUG
+ if (lease -> n_uid)
+ abort ();
+#endif
+
+ /* If it's not in the hash, just add it. */
+ if (!head)
+ add_hash (lease_uid_hash, lease -> uid,
+ lease -> uid_len, (unsigned char *)lease);
+ else {
+ /* Otherwise, attach it to the end of the list. */
+ for (scan = head; scan -> n_uid; scan = scan -> n_uid)
+#ifdef DEBUG
+ if (scan == lease)
+ abort ()
+#endif
+ ;
+ scan -> n_uid = lease;
+ }
+}
+
+/* Delete the specified lease from the uid hash. */
+
+void uid_hash_delete (lease)
+ struct lease *lease;
+{
+ struct lease *head =
+ find_lease_by_uid (lease -> uid, lease -> uid_len);
+ struct lease *scan;
+
+ /* If it's not in the hash, we have no work to do. */
+ if (!head) {
+ lease -> n_uid = (struct lease *)0;
+ return;
+ }
+
+ /* If the lease we're freeing is at the head of the list,
+ remove the hash table entry and add a new one with the
+ next lease on the list (if there is one). */
+ if (head == lease) {
+ delete_hash_entry (lease_uid_hash,
+ lease -> uid, lease -> uid_len);
+ if (lease -> n_uid)
+ add_hash (lease_uid_hash,
+ lease -> n_uid -> uid,
+ lease -> n_uid -> uid_len,
+ (unsigned char *)(lease -> n_uid));
+ } else {
+ /* Otherwise, look for the lease in the list of leases
+ attached to the hash table entry, and remove it if
+ we find it. */
+ for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
+ if (scan -> n_uid == lease) {
+ scan -> n_uid = scan -> n_uid -> n_uid;
+ break;
+ }
+ }
+ }
+ lease -> n_uid = (struct lease *)0;
+}
+
+/* Add the specified lease to the hardware address hash. */
+
+void hw_hash_add (lease)
+ struct lease *lease;
+{
+ struct lease *head =
+ find_lease_by_hw_addr (lease -> hardware_addr.haddr,
+ lease -> hardware_addr.hlen);
+ struct lease *scan;
+
+ /* If it's not in the hash, just add it. */
+ if (!head)
+ add_hash (lease_hw_addr_hash,
+ lease -> hardware_addr.haddr,
+ lease -> hardware_addr.hlen,
+ (unsigned char *)lease);
+ else {
+ /* Otherwise, attach it to the end of the list. */
+ for (scan = head; scan -> n_hw; scan = scan -> n_hw)
+ ;
+ scan -> n_hw = lease;
+ }
+}
+
+/* Delete the specified lease from the hardware address hash. */
+
+void hw_hash_delete (lease)
+ struct lease *lease;
+{
+ struct lease *head =
+ find_lease_by_hw_addr (lease -> hardware_addr.haddr,
+ lease -> hardware_addr.hlen);
+ struct lease *scan;
+
+ /* If it's not in the hash, we have no work to do. */
+ if (!head) {
+ lease -> n_hw = (struct lease *)0;
+ return;
+ }
+
+ /* If the lease we're freeing is at the head of the list,
+ remove the hash table entry and add a new one with the
+ next lease on the list (if there is one). */
+ if (head == lease) {
+ delete_hash_entry (lease_hw_addr_hash,
+ lease -> hardware_addr.haddr,
+ lease -> hardware_addr.hlen);
+ if (lease -> n_hw)
+ add_hash (lease_hw_addr_hash,
+ lease -> n_hw -> hardware_addr.haddr,
+ lease -> n_hw -> hardware_addr.hlen,
+ (unsigned char *)(lease -> n_hw));
+ } else {
+ /* Otherwise, look for the lease in the list of leases
+ attached to the hash table entry, and remove it if
+ we find it. */
+ for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
+ if (scan -> n_hw == lease) {
+ scan -> n_hw = scan -> n_hw -> n_hw;
+ break;
+ }
+ }
+ }
+ lease -> n_hw = (struct lease *)0;
+}
+
+
+struct class *add_class (type, name)
+ int type;
+ char *name;
+{
+ struct class *class = new_class ("add_class");
+ char *tname = (char *)malloc (strlen (name) + 1);
+
+ if (!vendor_class_hash)
+ vendor_class_hash = new_hash ();
+ if (!user_class_hash)
+ user_class_hash = new_hash ();
+
+ if (!tname || !class || !vendor_class_hash || !user_class_hash)
+ return (struct class *)0;
+
+ memset (class, 0, sizeof *class);
+ strcpy (tname, name);
+ class -> name = tname;
+
+ if (type)
+ add_hash (user_class_hash,
+ (unsigned char *)tname, strlen (tname),
+ (unsigned char *)class);
+ else
+ add_hash (vendor_class_hash,
+ (unsigned char *)tname, strlen (tname),
+ (unsigned char *)class);
+ return class;
+}
+
+struct class *find_class (type, name, len)
+ int type;
+ unsigned char *name;
+ int len;
+{
+ struct class *class =
+ (struct class *)hash_lookup (type
+ ? user_class_hash
+ : vendor_class_hash, name, len);
+ return class;
+}
+
+struct group *clone_group (group, caller)
+ struct group *group;
+ char *caller;
+{
+ struct group *g = new_group (caller);
+ if (!g)
+ error ("%s: can't allocate new group", caller);
+ *g = *group;
+ return g;
+}
+
+/* Write all interesting leases to permanent storage. */
+
+void write_leases ()
+{
+ struct lease *l;
+ struct shared_network *s;
+
+ for (s = shared_networks; s; s = s -> next) {
+ for (l = s -> leases; l; l = l -> next) {
+ if (l -> hardware_addr.hlen ||
+ l -> uid_len ||
+ (l -> flags & ABANDONED_LEASE))
+ if (!write_lease (l))
+ error ("Can't rewrite lease database");
+ }
+ }
+ if (!commit_leases ())
+ error ("Can't commit leases to new database: %m");
+}
+
+void dump_subnets ()
+{
+ struct lease *l;
+ struct shared_network *s;
+ struct subnet *n;
+
+ for (s = shared_networks; s; s = s -> next) {
+ for (n = subnets; n; n = n -> next_sibling) {
+ debug ("Subnet %s", piaddr (n -> net));
+ debug (" netmask %s",
+ piaddr (n -> netmask));
+ }
+ for (l = s -> leases; l; l = l -> next) {
+ print_lease (l);
+ }
+ debug ("Last Lease:");
+ print_lease (s -> last_lease);
+ }
+}
diff --git a/contrib/isc-dhcp/common/nit.c b/contrib/isc-dhcp/common/nit.c
new file mode 100644
index 000000000000..0633f1d393b0
--- /dev/null
+++ b/contrib/isc-dhcp/common/nit.c
@@ -0,0 +1,347 @@
+/* nit.c
+
+ Network Interface Tap (NIT) network interface code, by Ted Lemon
+ with one crucial tidbit of help from Stu Grossmen. */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''. */
+
+#ifndef lint
+static char copyright[] =
+"$Id: nit.c,v 1.15 1997/10/20 21:47:13 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE)
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <sys/time.h>
+#include <net/nit.h>
+#include <net/nit_if.h>
+#include <net/nit_pf.h>
+#include <net/nit_buf.h>
+#include <sys/stropts.h>
+#include <net/packetfilt.h>
+
+#include <netinet/in_systm.h>
+#include "includes/netinet/ip.h"
+#include "includes/netinet/udp.h"
+#include "includes/netinet/if_ether.h"
+
+/* Reinitializes the specified interface after an address change. This
+ is not required for packet-filter APIs. */
+
+#ifdef USE_NIT_SEND
+void if_reinitialize_send (info)
+ struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_NIT_RECEIVE
+void if_reinitialize_receive (info)
+ struct interface_info *info;
+{
+}
+#endif
+
+/* Called by get_interface_list for each interface that's discovered.
+ Opens a packet filter for each interface and adds it to the select
+ mask. */
+
+int if_register_nit (info)
+ struct interface_info *info;
+{
+ int sock;
+ char filename[50];
+ struct ifreq ifr;
+ struct strioctl sio;
+
+ /* Open a NIT device */
+ sock = open ("/dev/nit", O_RDWR);
+ if (sock < 0)
+ error ("Can't open NIT device for %s: %m", info -> name);
+
+ /* Set the NIT device to point at this interface. */
+ sio.ic_cmd = NIOCBIND;
+ sio.ic_len = sizeof *(info -> ifp);
+ sio.ic_dp = (char *)(info -> ifp);
+ sio.ic_timout = INFTIM;
+ if (ioctl (sock, I_STR, &sio) < 0)
+ error ("Can't attach interface %s to nit device: %m",
+ info -> name);
+
+ /* Get the low-level address... */
+ sio.ic_cmd = SIOCGIFADDR;
+ sio.ic_len = sizeof ifr;
+ sio.ic_dp = (char *)&ifr;
+ sio.ic_timout = INFTIM;
+ if (ioctl (sock, I_STR, &sio) < 0)
+ error ("Can't get physical layer address for %s: %m",
+ info -> name);
+
+ /* XXX code below assumes ethernet interface! */
+ info -> hw_address.hlen = 6;
+ info -> hw_address.htype = ARPHRD_ETHER;
+ memcpy (info -> hw_address.haddr, ifr.ifr_ifru.ifru_addr.sa_data, 6);
+
+ if (ioctl (sock, I_PUSH, "pf") < 0)
+ error ("Can't push packet filter onto NIT for %s: %m",
+ info -> name);
+
+ return sock;
+}
+#endif /* USE_NIT_SEND || USE_NIT_RECEIVE */
+
+#ifdef USE_NIT_SEND
+void if_register_send (info)
+ struct interface_info *info;
+{
+ /* If we're using the nit API for sending and receiving,
+ we don't need to register this interface twice. */
+#ifndef USE_NIT_RECEIVE
+ struct packetfilt pf;
+ struct strioctl sio;
+
+ info -> wfdesc = if_register_nit (info);
+
+ pf.Pf_Priority = 0;
+ pf.Pf_FilterLen = 1;
+ pf.Pf_Filter [0] = ENF_PUSHZERO;
+
+ /* Set up an NIT filter that rejects everything... */
+ sio.ic_cmd = NIOCSETF;
+ sio.ic_len = sizeof pf;
+ sio.ic_dp = (char *)&pf;
+ sio.ic_timout = INFTIM;
+ if (ioctl (info -> wfdesc, I_STR, &sio) < 0)
+ error ("Can't set NIT filter: %m");
+#else
+ info -> wfdesc = info -> rfdesc;
+#endif
+ if (!quiet_interface_discovery)
+ note ("Sending on NIT/%s/%s",
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_NIT_SEND */
+
+#ifdef USE_NIT_RECEIVE
+/* Packet filter program...
+ XXX Changes to the filter program may require changes to the constant
+ offsets used in if_register_send to patch the NIT program! XXX */
+
+void if_register_receive (info)
+ struct interface_info *info;
+{
+ int flag = 1;
+ u_int32_t x;
+ struct packetfilt pf;
+ struct strioctl sio;
+ u_int16_t addr [2];
+ struct timeval t;
+
+ /* Open a NIT device and hang it on this interface... */
+ info -> rfdesc = if_register_nit (info);
+
+ /* Set the snap length to 0, which means always take the whole
+ packet. */
+ x = 0;
+ if (ioctl (info -> rfdesc, NIOCSSNAP, &x) < 0)
+ error ("Can't set NIT snap length on %s: %m", info -> name);
+
+ /* Set the stream to byte stream mode */
+ if (ioctl (info -> rfdesc, I_SRDOPT, RMSGN) != 0)
+ note ("I_SRDOPT failed on %s: %m", info -> name);
+
+#if 0
+ /* Push on the chunker... */
+ if (ioctl (info -> rfdesc, I_PUSH, "nbuf") < 0)
+ error ("Can't push chunker onto NIT STREAM: %m");
+
+ /* Set the timeout to zero. */
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+ if (ioctl (info -> rfdesc, NIOCSTIME, &t) < 0)
+ error ("Can't set chunk timeout: %m");
+#endif
+
+ /* Ask for no header... */
+ x = 0;
+ if (ioctl (info -> rfdesc, NIOCSFLAGS, &x) < 0)
+ error ("Can't set NIT flags on %s: %m", info -> name);
+
+ /* Set up the NIT filter program. */
+ /* XXX Unlike the BPF filter program, this one won't work if the
+ XXX IP packet is fragmented or if there are options on the IP
+ XXX header. */
+ pf.Pf_Priority = 0;
+ pf.Pf_FilterLen = 0;
+
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 6;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = htons (ETHERTYPE_IP);
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = htons (IPPROTO_UDP);
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 11;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_AND;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = htons (0xFF);
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_CAND;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHWORD + 18;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
+ pf.Pf_Filter [pf.Pf_FilterLen++] = local_port;
+
+ /* Install the filter... */
+ sio.ic_cmd = NIOCSETF;
+ sio.ic_len = sizeof pf;
+ sio.ic_dp = (char *)&pf;
+ sio.ic_timout = INFTIM;
+ if (ioctl (info -> rfdesc, I_STR, &sio) < 0)
+ error ("Can't set NIT filter on %s: %m", info -> name);
+
+ if (!quiet_interface_discovery)
+ note ("Listening on NIT/%s/%s",
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_NIT_RECEIVE */
+
+#ifdef USE_NIT_SEND
+ssize_t send_packet (interface, packet, raw, len, from, to, hto)
+ struct interface_info *interface;
+ struct packet *packet;
+ struct dhcp_packet *raw;
+ size_t len;
+ struct in_addr from;
+ struct sockaddr_in *to;
+ struct hardware *hto;
+{
+ int bufp;
+ unsigned char buf [1536 + sizeof (struct sockaddr)];
+ struct sockaddr *junk;
+ struct strbuf ctl, data;
+ int hw_end;
+ struct sockaddr_in foo;
+
+ /* Start with the sockaddr struct... */
+ junk = (struct sockaddr *)&buf [0];
+ bufp = ((unsigned char *)&junk -> sa_data [0]) - &buf [0];
+
+ /* Assemble the headers... */
+ assemble_hw_header (interface, buf, &bufp, hto);
+ hw_end = bufp;
+ assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
+ to -> sin_addr.s_addr, to -> sin_port,
+ raw, len);
+
+ /* Copy the data into the buffer (yuk). */
+ memcpy (buf + bufp, raw, len);
+
+ /* Set up the sockaddr structure... */
+#if USE_SIN_LEN
+ junk -> sa_len = hw_end - 2; /* XXX */
+#endif
+ junk -> sa_family = AF_UNSPEC;
+
+#if 0 /* Already done. */
+ memcpy (junk.sa_data, buf, hw_len);
+#endif
+
+ /* Set up the msg_buf structure... */
+ ctl.buf = (char *)&buf [0];
+ ctl.maxlen = ctl.len = hw_end;
+ data.buf = (char *)&buf [hw_end];
+ data.maxlen = data.len = bufp + len - hw_end;
+
+ return putmsg (interface -> wfdesc, &ctl, &data, 0);
+}
+#endif /* USE_NIT_SEND */
+
+#ifdef USE_NIT_RECEIVE
+ssize_t receive_packet (interface, buf, len, from, hfrom)
+ struct interface_info *interface;
+ unsigned char *buf;
+ size_t len;
+ struct sockaddr_in *from;
+ struct hardware *hfrom;
+{
+ int nread;
+ int length = 0;
+ int offset = 0;
+ unsigned char ibuf [1536];
+ int bufix = 0;
+
+ length = read (interface -> rfdesc, ibuf, sizeof ibuf);
+ if (length <= 0)
+ return length;
+
+ /* Decode the physical header... */
+ offset = decode_hw_header (interface, ibuf, bufix, hfrom);
+
+ /* If a physical layer checksum failed (dunno of any
+ physical layer that supports this, but WTH), skip this
+ packet. */
+ if (offset < 0) {
+ return 0;
+ }
+
+ bufix += offset;
+ length -= offset;
+
+ /* Decode the IP and UDP headers... */
+ offset = decode_udp_ip_header (interface, ibuf, bufix,
+ from, (unsigned char *)0, length);
+
+ /* If the IP or UDP checksum was bad, skip the packet... */
+ if (offset < 0)
+ return 0;
+
+ bufix += offset;
+ length -= offset;
+
+ /* Copy out the data in the packet... */
+ memcpy (buf, &ibuf [bufix], length);
+ return length;
+}
+#endif
diff --git a/contrib/isc-dhcp/common/options.c b/contrib/isc-dhcp/common/options.c
new file mode 100644
index 000000000000..9d6b7f46ab46
--- /dev/null
+++ b/contrib/isc-dhcp/common/options.c
@@ -0,0 +1,609 @@
+/* options.c
+
+ DHCP options parsing and reassembly. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: options.c,v 1.26.2.3 1998/06/25 21:11:30 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#define DHCP_OPTION_DATA
+#include "dhcpd.h"
+
+/* Parse all available options out of the specified packet. */
+
+void parse_options (packet)
+ struct packet *packet;
+{
+ /* Initially, zero all option pointers. */
+ memset (packet -> options, 0, sizeof (packet -> options));
+
+ /* If we don't see the magic cookie, there's nothing to parse. */
+ if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
+ packet -> options_valid = 0;
+ return;
+ }
+
+ /* Go through the options field, up to the end of the packet
+ or the End field. */
+ parse_option_buffer (packet, &packet -> raw -> options [4],
+ packet -> packet_length - DHCP_FIXED_NON_UDP - 4);
+ /* If we parsed a DHCP Option Overload option, parse more
+ options out of the buffer(s) containing them. */
+ if (packet -> options_valid
+ && packet -> options [DHO_DHCP_OPTION_OVERLOAD].data) {
+ if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 1)
+ parse_option_buffer (packet,
+ (unsigned char *)
+ packet -> raw -> file,
+ sizeof packet -> raw -> file);
+ if (packet -> options [DHO_DHCP_OPTION_OVERLOAD].data [0] & 2)
+ parse_option_buffer (packet,
+ (unsigned char *)
+ packet -> raw -> sname,
+ sizeof packet -> raw -> sname);
+ }
+}
+
+/* Parse options out of the specified buffer, storing addresses of option
+ values in packet -> options and setting packet -> options_valid if no
+ errors are encountered. */
+
+void parse_option_buffer (packet, buffer, length)
+ struct packet *packet;
+ unsigned char *buffer;
+ int length;
+{
+ unsigned char *s, *t;
+ unsigned char *end = buffer + length;
+ int len;
+ int code;
+
+ for (s = buffer; *s != DHO_END && s < end; ) {
+ code = s [0];
+ /* Pad options don't have a length - just skip them. */
+ if (code == DHO_PAD) {
+ ++s;
+ continue;
+ }
+ /* All other fields (except end, see above) have a
+ one-byte length. */
+ len = s [1];
+
+ /* If the length is outrageous, the options are bad. */
+ if (s + len + 2 > end) {
+ warn ("Option %s length %d overflows input buffer.",
+ dhcp_options [code].name,
+ len);
+ packet -> options_valid = 0;
+ return;
+ }
+ /* If we haven't seen this option before, just make
+ space for it and copy it there. */
+ if (!packet -> options [code].data) {
+ if (!(t = (unsigned char *)malloc (len + 1)))
+ error ("Can't allocate storage for option %s.",
+ dhcp_options [code].name);
+ /* Copy and NUL-terminate the option (in case it's an
+ ASCII string. */
+ memcpy (t, &s [2], len);
+ t [len] = 0;
+ packet -> options [code].len = len;
+ packet -> options [code].data = t;
+ } else {
+ /* If it's a repeat, concatenate it to whatever
+ we last saw. This is really only required
+ for clients, but what the heck... */
+ t = (unsigned char *)
+ malloc (len
+ + packet -> options [code].len
+ + 1);
+ if (!t)
+ error ("Can't expand storage for option %s.",
+ dhcp_options [code].name);
+ memcpy (t, packet -> options [code].data,
+ packet -> options [code].len);
+ memcpy (t + packet -> options [code].len,
+ &s [2], len);
+ packet -> options [code].len += len;
+ t [packet -> options [code].len] = 0;
+ free (packet -> options [code].data);
+ packet -> options [code].data = t;
+ }
+ s += len + 2;
+ }
+ packet -> options_valid = 1;
+}
+
+/* cons options into a big buffer, and then split them out into the
+ three seperate buffers if needed. This allows us to cons up a set
+ of vendor options using the same routine. */
+
+int cons_options (inpacket, outpacket, options, overload, terminate, bootpp)
+ struct packet *inpacket;
+ struct dhcp_packet *outpacket;
+ struct tree_cache **options;
+ int overload; /* Overload flags that may be set. */
+ int terminate;
+ int bootpp;
+{
+ unsigned char priority_list [300];
+ int priority_len;
+ unsigned char buffer [4096]; /* Really big buffer... */
+ int main_buffer_size;
+ int mainbufix, bufix;
+ int option_size;
+ int length;
+
+ /* If the client has provided a maximum DHCP message size,
+ use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
+ use up to the minimum IP MTU size (576 bytes). */
+ /* XXX if a BOOTP client specifies a max message size, we will
+ honor it. */
+ if (inpacket && inpacket -> options [DHO_DHCP_MAX_MESSAGE_SIZE].data) {
+ main_buffer_size =
+ (getUShort (inpacket -> options
+ [DHO_DHCP_MAX_MESSAGE_SIZE].data)
+ - DHCP_FIXED_LEN);
+ /* Enforce a minimum packet size... */
+ if (main_buffer_size < (576 - DHCP_FIXED_LEN))
+ main_buffer_size = 576 - DHCP_FIXED_LEN;
+ if (main_buffer_size > sizeof buffer)
+ main_buffer_size = sizeof buffer;
+ } else if (bootpp)
+ main_buffer_size = 64;
+ else
+ main_buffer_size = 576 - DHCP_FIXED_LEN;
+
+ /* Preload the option priority list with mandatory options. */
+ priority_len = 0;
+ priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE;
+ priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
+ priority_list [priority_len++] = DHO_DHCP_LEASE_TIME;
+ priority_list [priority_len++] = DHO_DHCP_MESSAGE;
+
+ /* If the client has provided a list of options that it wishes
+ returned, use it to prioritize. Otherwise, prioritize
+ based on the default priority list. */
+
+ if (inpacket &&
+ inpacket -> options [DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
+ int prlen = (inpacket ->
+ options [DHO_DHCP_PARAMETER_REQUEST_LIST].len);
+ if (prlen + priority_len > sizeof priority_list)
+ prlen = (sizeof priority_list) - priority_len;
+
+ memcpy (&priority_list [priority_len],
+ inpacket -> options
+ [DHO_DHCP_PARAMETER_REQUEST_LIST].data, prlen);
+ priority_len += prlen;
+ } else {
+ memcpy (&priority_list [priority_len],
+ dhcp_option_default_priority_list,
+ sizeof_dhcp_option_default_priority_list);
+ priority_len += sizeof_dhcp_option_default_priority_list;
+ }
+
+ /* Copy the options into the big buffer... */
+ option_size = store_options (buffer,
+ (main_buffer_size - 7 +
+ ((overload & 1) ? DHCP_FILE_LEN : 0) +
+ ((overload & 2) ? DHCP_SNAME_LEN : 0)),
+ options, priority_list, priority_len,
+ main_buffer_size,
+ (main_buffer_size +
+ ((overload & 1) ? DHCP_FILE_LEN : 0)),
+ terminate);
+
+ /* Put the cookie up front... */
+ memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4);
+ mainbufix = 4;
+
+ /* If we're going to have to overload, store the overload
+ option at the beginning. If we can, though, just store the
+ whole thing in the packet's option buffer and leave it at
+ that. */
+ if (option_size <= main_buffer_size - mainbufix) {
+ memcpy (&outpacket -> options [mainbufix],
+ buffer, option_size);
+ mainbufix += option_size;
+ if (mainbufix < main_buffer_size)
+ outpacket -> options [mainbufix++]
+ = DHO_END;
+ length = DHCP_FIXED_NON_UDP + mainbufix;
+ } else {
+ outpacket -> options [mainbufix++] =
+ DHO_DHCP_OPTION_OVERLOAD;
+ outpacket -> options [mainbufix++] = 1;
+ if (option_size > main_buffer_size - mainbufix + DHCP_FILE_LEN)
+ outpacket -> options [mainbufix++] = 3;
+ else
+ outpacket -> options [mainbufix++] = 1;
+
+ memcpy (&outpacket -> options [mainbufix],
+ buffer, main_buffer_size - mainbufix);
+ bufix = main_buffer_size - mainbufix;
+ length = DHCP_FIXED_NON_UDP + mainbufix;
+ if (overload & 1) {
+ if (option_size - bufix <= DHCP_FILE_LEN) {
+ memcpy (outpacket -> file,
+ &buffer [bufix], option_size - bufix);
+ mainbufix = option_size - bufix;
+ if (mainbufix < DHCP_FILE_LEN)
+ outpacket -> file [mainbufix++]
+ = DHO_END;
+ while (mainbufix < DHCP_FILE_LEN)
+ outpacket -> file [mainbufix++]
+ = DHO_PAD;
+ } else {
+ memcpy (outpacket -> file,
+ &buffer [bufix], DHCP_FILE_LEN);
+ bufix += DHCP_FILE_LEN;
+ }
+ }
+ if ((overload & 2) && option_size < bufix) {
+ memcpy (outpacket -> sname,
+ &buffer [bufix], option_size - bufix);
+
+ mainbufix = option_size - bufix;
+ if (mainbufix < DHCP_SNAME_LEN)
+ outpacket -> file [mainbufix++]
+ = DHO_END;
+ while (mainbufix < DHCP_SNAME_LEN)
+ outpacket -> file [mainbufix++]
+ = DHO_PAD;
+ }
+ }
+ return length;
+}
+
+/* Store all the requested options into the requested buffer. */
+
+int store_options (buffer, buflen, options, priority_list, priority_len,
+ first_cutoff, second_cutoff, terminate)
+ unsigned char *buffer;
+ int buflen;
+ struct tree_cache **options;
+ unsigned char *priority_list;
+ int priority_len;
+ int first_cutoff, second_cutoff;
+ int terminate;
+{
+ int bufix = 0;
+ int option_stored [256];
+ int i;
+ int ix;
+ int tto;
+
+ /* Zero out the stored-lengths array. */
+ memset (option_stored, 0, sizeof option_stored);
+
+ /* Copy out the options in the order that they appear in the
+ priority list... */
+ for (i = 0; i < priority_len; i++) {
+ /* Code for next option to try to store. */
+ int code = priority_list [i];
+ int optstart;
+
+ /* Number of bytes left to store (some may already
+ have been stored by a previous pass). */
+ int length;
+
+ /* If no data is available for this option, skip it. */
+ if (!options [code]) {
+ continue;
+ }
+
+ /* The client could ask for things that are mandatory,
+ in which case we should avoid storing them twice... */
+ if (option_stored [code])
+ continue;
+ option_stored [code] = 1;
+
+ /* Find the value of the option... */
+ if (!tree_evaluate (options [code])) {
+ continue;
+ }
+
+ /* We should now have a constant length for the option. */
+ length = options [code] -> len;
+
+ /* Do we add a NUL? */
+ if (terminate && dhcp_options [code].format [0] == 't') {
+ length++;
+ tto = 1;
+ } else {
+ tto = 0;
+ }
+
+ /* Try to store the option. */
+
+ /* If the option's length is more than 255, we must store it
+ in multiple hunks. Store 255-byte hunks first. However,
+ in any case, if the option data will cross a buffer
+ boundary, split it across that boundary. */
+
+ ix = 0;
+
+ optstart = bufix;
+ while (length) {
+ unsigned char incr = length > 255 ? 255 : length;
+
+ /* If this hunk of the buffer will cross a
+ boundary, only go up to the boundary in this
+ pass. */
+ if (bufix < first_cutoff &&
+ bufix + incr > first_cutoff)
+ incr = first_cutoff - bufix;
+ else if (bufix < second_cutoff &&
+ bufix + incr > second_cutoff)
+ incr = second_cutoff - bufix;
+
+ /* If this option is going to overflow the buffer,
+ skip it. */
+ if (bufix + 2 + incr > buflen) {
+ bufix = optstart;
+ break;
+ }
+
+ /* Everything looks good - copy it in! */
+ buffer [bufix] = code;
+ buffer [bufix + 1] = incr;
+ if (tto && incr == length) {
+ memcpy (buffer + bufix + 2,
+ options [code] -> value + ix,
+ incr - 1);
+ buffer [bufix + 2 + incr - 1] = 0;
+ } else {
+ memcpy (buffer + bufix + 2,
+ options [code] -> value + ix, incr);
+ }
+ length -= incr;
+ ix += incr;
+ bufix += 2 + incr;
+ }
+ }
+ return bufix;
+}
+
+/* Format the specified option so that a human can easily read it. */
+
+char *pretty_print_option (code, data, len, emit_commas, emit_quotes)
+ unsigned int code;
+ unsigned char *data;
+ int len;
+ int emit_commas;
+ int emit_quotes;
+{
+ static char optbuf [32768]; /* XXX */
+ int hunksize = 0;
+ int numhunk = -1;
+ int numelem = 0;
+ char fmtbuf [32];
+ int i, j;
+ char *op = optbuf;
+ unsigned char *dp = data;
+ struct in_addr foo;
+ char comma;
+
+ /* Code should be between 0 and 255. */
+ if (code > 255)
+ error ("pretty_print_option: bad code %d\n", code);
+
+ if (emit_commas)
+ comma = ',';
+ else
+ comma = ' ';
+
+ /* Figure out the size of the data. */
+ for (i = 0; dhcp_options [code].format [i]; i++) {
+ if (!numhunk) {
+ warn ("%s: Excess information in format string: %s\n",
+ dhcp_options [code].name,
+ &(dhcp_options [code].format [i]));
+ break;
+ }
+ numelem++;
+ fmtbuf [i] = dhcp_options [code].format [i];
+ switch (dhcp_options [code].format [i]) {
+ case 'A':
+ --numelem;
+ fmtbuf [i] = 0;
+ numhunk = 0;
+ break;
+ case 'X':
+ fmtbuf [i] = 'x';
+ fmtbuf [i + 1] = 0;
+ hunksize++;
+ numhunk = 0;
+ comma = ':';
+ break;
+ case 't':
+ fmtbuf [i] = 't';
+ fmtbuf [i + 1] = 0;
+ numhunk = -2;
+ break;
+ case 'I':
+ case 'l':
+ case 'L':
+ hunksize += 4;
+ break;
+ case 's':
+ case 'S':
+ hunksize += 2;
+ break;
+ case 'b':
+ case 'B':
+ case 'f':
+ hunksize++;
+ break;
+ case 'e':
+ break;
+ default:
+ warn ("%s: garbage in format string: %s\n",
+ dhcp_options [code].name,
+ &(dhcp_options [code].format [i]));
+ break;
+ }
+ }
+
+ /* Check for too few bytes... */
+ if (hunksize > len) {
+ warn ("%s: expecting at least %d bytes; got %d",
+ dhcp_options [code].name,
+ hunksize, len);
+ return "<error>";
+ }
+ /* Check for too many bytes... */
+ if (numhunk == -1 && hunksize < len)
+ warn ("%s: %d extra bytes",
+ dhcp_options [code].name,
+ len - hunksize);
+
+ /* If this is an array, compute its size. */
+ if (!numhunk)
+ numhunk = len / hunksize;
+ /* See if we got an exact number of hunks. */
+ if (numhunk > 0 && numhunk * hunksize < len)
+ warn ("%s: %d extra bytes at end of array\n",
+ dhcp_options [code].name,
+ len - numhunk * hunksize);
+
+ /* A one-hunk array prints the same as a single hunk. */
+ if (numhunk < 0)
+ numhunk = 1;
+
+ /* Cycle through the array (or hunk) printing the data. */
+ for (i = 0; i < numhunk; i++) {
+ for (j = 0; j < numelem; j++) {
+ switch (fmtbuf [j]) {
+ case 't':
+ if (emit_quotes)
+ *op++ = '"';
+ strcpy (op, (char *)dp);
+ op += strlen ((char *)dp);
+ if (emit_quotes)
+ *op++ = '"';
+ *op = 0;
+ break;
+ case 'I':
+ foo.s_addr = htonl (getULong (dp));
+ strcpy (op, inet_ntoa (foo));
+ dp += 4;
+ break;
+ case 'l':
+ sprintf (op, "%ld", (long)getLong (dp));
+ dp += 4;
+ break;
+ case 'L':
+ sprintf (op, "%ld",
+ (unsigned long)getULong (dp));
+ dp += 4;
+ break;
+ case 's':
+ sprintf (op, "%d", getShort (dp));
+ dp += 2;
+ break;
+ case 'S':
+ sprintf (op, "%d", getUShort (dp));
+ dp += 2;
+ break;
+ case 'b':
+ sprintf (op, "%d", *(char *)dp++);
+ break;
+ case 'B':
+ sprintf (op, "%d", *dp++);
+ break;
+ case 'x':
+ sprintf (op, "%x", *dp++);
+ break;
+ case 'f':
+ strcpy (op, *dp++ ? "true" : "false");
+ break;
+ default:
+ warn ("Unexpected format code %c", fmtbuf [j]);
+ }
+ op += strlen (op);
+ if (j + 1 < numelem && comma != ':')
+ *op++ = ' ';
+ }
+ if (i + 1 < numhunk) {
+ *op++ = comma;
+ }
+
+ }
+ return optbuf;
+}
+
+void do_packet (interface, packet, len, from_port, from, hfrom)
+ struct interface_info *interface;
+ struct dhcp_packet *packet;
+ int len;
+ unsigned int from_port;
+ struct iaddr from;
+ struct hardware *hfrom;
+{
+ struct packet tp;
+
+ if (packet -> hlen > sizeof packet -> chaddr) {
+ note ("Discarding packet with invalid hlen.");
+ return;
+ }
+
+ memset (&tp, 0, sizeof tp);
+ tp.raw = packet;
+ tp.packet_length = len;
+ tp.client_port = from_port;
+ tp.client_addr = from;
+ tp.interface = interface;
+ tp.haddr = hfrom;
+
+ parse_options (&tp);
+ if (tp.options_valid &&
+ tp.options [DHO_DHCP_MESSAGE_TYPE].data)
+ tp.packet_type =
+ tp.options [DHO_DHCP_MESSAGE_TYPE].data [0];
+ if (tp.packet_type)
+ dhcp (&tp);
+ else
+ bootp (&tp);
+}
+
diff --git a/contrib/isc-dhcp/common/packet.c b/contrib/isc-dhcp/common/packet.c
new file mode 100644
index 000000000000..069a76b81762
--- /dev/null
+++ b/contrib/isc-dhcp/common/packet.c
@@ -0,0 +1,311 @@
+/* packet.c
+
+ Packet assembly code, originally contributed by Archie Cobbs. */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: packet.c,v 1.18.2.1 1998/06/26 18:20:44 mellon Exp $ Copyright (c) 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+#if defined (PACKET_ASSEMBLY) || defined (PACKET_DECODING)
+#include "includes/netinet/ip.h"
+#include "includes/netinet/udp.h"
+#include "includes/netinet/if_ether.h"
+#endif /* PACKET_ASSEMBLY || PACKET_DECODING */
+
+/* Compute the easy part of the checksum on a range of bytes. */
+
+u_int32_t checksum (buf, nbytes, sum)
+ unsigned char *buf;
+ int nbytes;
+ u_int32_t sum;
+{
+ int i;
+
+#ifdef DEBUG_CHECKSUM
+ debug ("checksum (%x %d %x)", buf, nbytes, sum);
+#endif
+
+ /* Checksum all the pairs of bytes first... */
+ for (i = 0; i < (nbytes & ~1); i += 2) {
+#ifdef DEBUG_CHECKSUM_VERBOSE
+ debug ("sum = %x", sum);
+#endif
+ sum += (u_int16_t) ntohs(*((u_int16_t *)(buf + i)));
+ }
+
+ /* If there's a single byte left over, checksum it, too. Network
+ byte order is big-endian, so the remaining byte is the high byte. */
+ if (i < nbytes) {
+#ifdef DEBUG_CHECKSUM_VERBOSE
+ debug ("sum = %x", sum);
+#endif
+ sum += buf [i] << 8;
+ }
+
+ return sum;
+}
+
+/* Fold the upper sixteen bits of the checksum down into the lower bits,
+ complement the sum, and then put it into network byte order. */
+
+u_int32_t wrapsum (sum)
+ u_int32_t sum;
+{
+#ifdef DEBUG_CHECKSUM
+ debug ("wrapsum (%x)", sum);
+#endif
+
+ while (sum > 0x10000) {
+ sum = (sum >> 16) + (sum & 0xFFFF);
+#ifdef DEBUG_CHECKSUM_VERBOSE
+ debug ("sum = %x", sum);
+#endif
+ sum += (sum >> 16);
+#ifdef DEBUG_CHECKSUM_VERBOSE
+ debug ("sum = %x", sum);
+#endif
+ }
+ sum = sum ^ 0xFFFF;
+#ifdef DEBUG_CHECKSUM_VERBOSE
+ debug ("sum = %x", sum);
+#endif
+
+#ifdef DEBUG_CHECKSUM
+ debug ("wrapsum returns %x", htons (sum));
+#endif
+ return htons(sum);
+}
+
+#ifdef PACKET_ASSEMBLY
+/* Assemble an hardware header... */
+/* XXX currently only supports ethernet; doesn't check for other types. */
+
+void assemble_hw_header (interface, buf, bufix, to)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int *bufix;
+ struct hardware *to;
+{
+ struct ether_header eh;
+
+ if (to && to -> hlen == 6) /* XXX */
+ memcpy (eh.ether_dhost, to -> haddr, sizeof eh.ether_dhost);
+ else
+ memset (eh.ether_dhost, 0xff, sizeof (eh.ether_dhost));
+ if (interface -> hw_address.hlen == sizeof (eh.ether_shost))
+ memcpy (eh.ether_shost, interface -> hw_address.haddr,
+ sizeof (eh.ether_shost));
+ else
+ memset (eh.ether_shost, 0x00, sizeof (eh.ether_shost));
+
+#ifdef BROKEN_FREEBSD_BPF /* Fixed in FreeBSD 2.2 */
+ eh.ether_type = ETHERTYPE_IP;
+#else
+ eh.ether_type = htons (ETHERTYPE_IP);
+#endif
+
+ memcpy (&buf [*bufix], &eh, sizeof eh);
+ *bufix += sizeof eh;
+}
+
+/* UDP header and IP header assembled together for convenience. */
+
+void assemble_udp_ip_header (interface, buf, bufix,
+ from, to, port, data, len)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int *bufix;
+ u_int32_t from;
+ u_int32_t to;
+ unsigned int port;
+ unsigned char *data;
+ int len;
+{
+ struct ip ip;
+ struct udphdr udp;
+
+ /* Fill out the IP header */
+ ip.ip_v = 4;
+ ip.ip_hl = 5;
+ ip.ip_tos = IPTOS_LOWDELAY;
+ ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len);
+ ip.ip_id = 0;
+ ip.ip_off = 0;
+ ip.ip_ttl = 16;
+ ip.ip_p = IPPROTO_UDP;
+ ip.ip_sum = 0;
+ ip.ip_src.s_addr = from;
+ ip.ip_dst.s_addr = to;
+
+ /* Checksum the IP header... */
+ ip.ip_sum = wrapsum (checksum ((unsigned char *)&ip, sizeof ip, 0));
+
+ /* Copy the ip header into the buffer... */
+ memcpy (&buf [*bufix], &ip, sizeof ip);
+ *bufix += sizeof ip;
+
+ /* Fill out the UDP header */
+ udp.uh_sport = local_port; /* XXX */
+ udp.uh_dport = port; /* XXX */
+ udp.uh_ulen = htons(sizeof(udp) + len);
+ memset (&udp.uh_sum, 0, sizeof udp.uh_sum);
+
+ /* Compute UDP checksums, including the ``pseudo-header'', the UDP
+ header and the data. */
+
+#if 0
+ udp.uh_sum =
+ wrapsum (checksum ((unsigned char *)&udp, sizeof udp,
+ checksum (data, len,
+ checksum ((unsigned char *)
+ &ip.ip_src,
+ sizeof ip.ip_src,
+ IPPROTO_UDP +
+ (u_int32_t)
+ ntohs (udp.uh_ulen)))));
+#endif
+
+ /* Copy the udp header into the buffer... */
+ memcpy (&buf [*bufix], &udp, sizeof udp);
+ *bufix += sizeof udp;
+}
+#endif /* PACKET_ASSEMBLY */
+
+#ifdef PACKET_DECODING
+/* Decode a hardware header... */
+/* XXX currently only supports ethernet; doesn't check for other types. */
+
+ssize_t decode_hw_header (interface, buf, bufix, from)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int bufix;
+ struct hardware *from;
+{
+ struct ether_header eh;
+
+ memcpy (&eh, buf + bufix, sizeof eh);
+
+#ifdef USERLAND_FILTER
+ if (ntohs (eh.ether_type) != ETHERTYPE_IP)
+ return -1;
+#endif
+ memcpy (from -> haddr, eh.ether_shost, sizeof (eh.ether_shost));
+ from -> htype = ARPHRD_ETHER;
+ from -> hlen = sizeof eh.ether_shost;
+
+ return sizeof eh;
+}
+
+/* UDP header and IP header decoded together for convenience. */
+
+ssize_t decode_udp_ip_header (interface, buf, bufix, from, data, len)
+ struct interface_info *interface;
+ unsigned char *buf;
+ int bufix;
+ struct sockaddr_in *from;
+ unsigned char *data;
+ int len;
+{
+ struct ip *ip;
+ struct udphdr *udp;
+ u_int32_t ip_len = (buf [bufix] & 0xf) << 2;
+ u_int32_t sum, usum;
+
+ ip = (struct ip *)(buf + bufix);
+ udp = (struct udphdr *)(buf + bufix + ip_len);
+
+#ifdef USERLAND_FILTER
+ /* Is it a UDP packet? */
+ if (ip -> ip_p != IPPROTO_UDP)
+ return -1;
+
+ /* Is it to the port we're serving? */
+ if (udp -> uh_dport != local_port)
+ return -1;
+#endif /* USERLAND_FILTER */
+
+ /* Check the IP header checksum - it should be zero. */
+ if (wrapsum (checksum (buf + bufix, ip_len, 0))) {
+ note ("Bad IP checksum: %x",
+ wrapsum (checksum (buf + bufix, sizeof *ip, 0)));
+ return -1;
+ }
+
+ /* Copy out the IP source address... */
+ memcpy (&from -> sin_addr, &ip -> ip_src, 4);
+
+ /* Compute UDP checksums, including the ``pseudo-header'', the UDP
+ header and the data. If the UDP checksum field is zero, we're
+ not supposed to do a checksum. */
+
+ if (!data) {
+ data = buf + bufix + ip_len + sizeof *udp;
+ len -= ip_len + sizeof *udp;
+ }
+
+#if 0
+ usum = udp -> uh_sum;
+ udp -> uh_sum = 0;
+
+ sum = wrapsum (checksum ((unsigned char *)udp, sizeof *udp,
+ checksum (data, len,
+ checksum ((unsigned char *)
+ &ip -> ip_src,
+ sizeof ip -> ip_src,
+ IPPROTO_UDP +
+ (u_int32_t)
+ ntohs (udp -> uh_ulen)))));
+
+ if (usum && usum != sum) {
+ note ("Bad udp checksum: %x %x", usum, sum);
+ return -1;
+ }
+#endif
+
+ /* Copy out the port... */
+ memcpy (&from -> sin_port, &udp -> uh_sport, sizeof udp -> uh_sport);
+
+ return ip_len + sizeof *udp;
+}
+#endif /* PACKET_DECODING */
diff --git a/contrib/isc-dhcp/common/parse.c b/contrib/isc-dhcp/common/parse.c
new file mode 100644
index 000000000000..97bfa877b17e
--- /dev/null
+++ b/contrib/isc-dhcp/common/parse.c
@@ -0,0 +1,643 @@
+/* parse.c
+
+ Common parser code for dhcpd and dhclient. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: parse.c,v 1.2.2.1 1998/06/25 21:11:31 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+/* Skip to the semicolon ending the current statement. If we encounter
+ braces, the matching closing brace terminates the statement. If we
+ encounter a right brace but haven't encountered a left brace, return
+ leaving the brace in the token buffer for the caller. If we see a
+ semicolon and haven't seen a left brace, return. This lets us skip
+ over:
+
+ statement;
+ statement foo bar { }
+ statement foo bar { statement { } }
+ statement}
+
+ ...et cetera. */
+
+void skip_to_semi (cfile)
+ FILE *cfile;
+{
+ int token;
+ char *val;
+ int brace_count = 0;
+
+ do {
+ token = peek_token (&val, cfile);
+ if (token == RBRACE) {
+ if (brace_count) {
+ token = next_token (&val, cfile);
+ if (!--brace_count)
+ return;
+ } else
+ return;
+ } else if (token == LBRACE) {
+ brace_count++;
+ } else if (token == SEMI && !brace_count) {
+ token = next_token (&val, cfile);
+ return;
+ } else if (token == EOL) {
+ /* EOL only happens when parsing /etc/resolv.conf,
+ and we treat it like a semicolon because the
+ resolv.conf file is line-oriented. */
+ token = next_token (&val, cfile);
+ return;
+ }
+ token = next_token (&val, cfile);
+ } while (token != EOF);
+}
+
+int parse_semi (cfile)
+ FILE *cfile;
+{
+ int token;
+ char *val;
+
+ token = next_token (&val, cfile);
+ if (token != SEMI) {
+ parse_warn ("semicolon expected.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+ return 1;
+}
+
+/* string-parameter :== STRING SEMI */
+
+char *parse_string (cfile)
+ FILE *cfile;
+{
+ char *val;
+ int token;
+ char *s;
+
+ token = next_token (&val, cfile);
+ if (token != STRING) {
+ parse_warn ("filename must be a string");
+ skip_to_semi (cfile);
+ return (char *)0;
+ }
+ s = (char *)malloc (strlen (val) + 1);
+ if (!s)
+ error ("no memory for string %s.", val);
+ strcpy (s, val);
+
+ if (!parse_semi (cfile))
+ return (char *)0;
+ return s;
+}
+
+/* hostname :== identifier | hostname DOT identifier */
+
+char *parse_host_name (cfile)
+ FILE *cfile;
+{
+ char *val;
+ int token;
+ int len = 0;
+ char *s;
+ char *t;
+ pair c = (pair)0;
+
+ /* Read a dotted hostname... */
+ do {
+ /* Read a token, which should be an identifier. */
+ token = next_token (&val, cfile);
+ if (!is_identifier (token) && token != NUMBER) {
+ parse_warn ("expecting an identifier in hostname");
+ skip_to_semi (cfile);
+ return (char *)0;
+ }
+ /* Store this identifier... */
+ if (!(s = (char *)malloc (strlen (val) + 1)))
+ error ("can't allocate temp space for hostname.");
+ strcpy (s, val);
+ c = cons ((caddr_t)s, c);
+ len += strlen (s) + 1;
+ /* Look for a dot; if it's there, keep going, otherwise
+ we're done. */
+ token = peek_token (&val, cfile);
+ if (token == DOT)
+ token = next_token (&val, cfile);
+ } while (token == DOT);
+
+ /* Assemble the hostname together into a string. */
+ if (!(s = (char *)malloc (len)))
+ error ("can't allocate space for hostname.");
+ t = s + len;
+ *--t = 0;
+ while (c) {
+ pair cdr = c -> cdr;
+ int l = strlen ((char *)(c -> car));
+ t -= l;
+ memcpy (t, (char *)(c -> car), l);
+ /* Free up temp space. */
+ free (c -> car);
+ free (c);
+ c = cdr;
+ if (t != s)
+ *--t = '.';
+ }
+ return s;
+}
+
+int parse_ip_addr (cfile, addr)
+ FILE *cfile;
+ struct iaddr *addr;
+{
+ char *val;
+ int token;
+
+ addr -> len = 4;
+ if (parse_numeric_aggregate (cfile, addr -> iabuf,
+ &addr -> len, DOT, 10, 8))
+ return 1;
+ return 0;
+}
+
+/* hardware-parameter :== HARDWARE ETHERNET csns SEMI
+ csns :== NUMBER | csns COLON NUMBER */
+
+void parse_hardware_param (cfile, hardware)
+ FILE *cfile;
+ struct hardware *hardware;
+{
+ char *val;
+ int token;
+ int hlen;
+ unsigned char *t;
+
+ token = next_token (&val, cfile);
+ switch (token) {
+ case ETHERNET:
+ hardware -> htype = HTYPE_ETHER;
+ break;
+ case TOKEN_RING:
+ hardware -> htype = HTYPE_IEEE802;
+ break;
+ default:
+ parse_warn ("expecting a network hardware type");
+ skip_to_semi (cfile);
+ return;
+ }
+
+ /* Parse the hardware address information. Technically,
+ it would make a lot of sense to restrict the length of the
+ data we'll accept here to the length of a particular hardware
+ address type. Unfortunately, there are some broken clients
+ out there that put bogus data in the chaddr buffer, and we accept
+ that data in the lease file rather than simply failing on such
+ clients. Yuck. */
+ hlen = 0;
+ t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen,
+ COLON, 16, 8);
+ if (!t)
+ return;
+ if (hlen > sizeof hardware -> haddr) {
+ free (t);
+ parse_warn ("hardware address too long");
+ } else {
+ hardware -> hlen = hlen;
+ memcpy ((unsigned char *)&hardware -> haddr [0],
+ t, hardware -> hlen);
+ free (t);
+ }
+
+ token = next_token (&val, cfile);
+ if (token != SEMI) {
+ parse_warn ("expecting semicolon.");
+ skip_to_semi (cfile);
+ }
+}
+
+/* lease-time :== NUMBER SEMI */
+
+void parse_lease_time (cfile, timep)
+ FILE *cfile;
+ TIME *timep;
+{
+ char *val;
+ int token;
+
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("Expecting numeric lease time");
+ skip_to_semi (cfile);
+ return;
+ }
+ convert_num ((unsigned char *)timep, val, 10, 32);
+ /* Unswap the number - convert_num returns stuff in NBO. */
+ *timep = ntohl (*timep); /* XXX */
+
+ parse_semi (cfile);
+}
+
+/* No BNF for numeric aggregates - that's defined by the caller. What
+ this function does is to parse a sequence of numbers seperated by
+ the token specified in seperator. If max is zero, any number of
+ numbers will be parsed; otherwise, exactly max numbers are
+ expected. Base and size tell us how to internalize the numbers
+ once they've been tokenized. */
+
+unsigned char *parse_numeric_aggregate (cfile, buf,
+ max, seperator, base, size)
+ FILE *cfile;
+ unsigned char *buf;
+ int *max;
+ int seperator;
+ int base;
+ int size;
+{
+ char *val;
+ int token;
+ unsigned char *bufp = buf, *s;
+ char *t;
+ int count = 0;
+ pair c = (pair)0;
+
+ if (!bufp && *max) {
+ bufp = (unsigned char *)malloc (*max * size / 8);
+ if (!bufp)
+ error ("can't allocate space for numeric aggregate");
+ } else
+ s = bufp;
+
+ do {
+ if (count) {
+ token = peek_token (&val, cfile);
+ if (token != seperator) {
+ if (!*max)
+ break;
+ if (token != RBRACE && token != LBRACE)
+ token = next_token (&val, cfile);
+ parse_warn ("too few numbers.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (unsigned char *)0;
+ }
+ token = next_token (&val, cfile);
+ }
+ token = next_token (&val, cfile);
+
+ if (token == EOF) {
+ parse_warn ("unexpected end of file");
+ break;
+ }
+
+ /* Allow NUMBER_OR_NAME if base is 16. */
+ if (token != NUMBER &&
+ (base != 16 || token != NUMBER_OR_NAME)) {
+ parse_warn ("expecting numeric value.");
+ skip_to_semi (cfile);
+ return (unsigned char *)0;
+ }
+ /* If we can, convert the number now; otherwise, build
+ a linked list of all the numbers. */
+ if (s) {
+ convert_num (s, val, base, size);
+ s += size / 8;
+ } else {
+ t = (char *)malloc (strlen (val) + 1);
+ if (!t)
+ error ("no temp space for number.");
+ strcpy (t, val);
+ c = cons (t, c);
+ }
+ } while (++count != *max);
+
+ /* If we had to cons up a list, convert it now. */
+ if (c) {
+ bufp = (unsigned char *)malloc (count * size / 8);
+ if (!bufp)
+ error ("can't allocate space for numeric aggregate.");
+ s = bufp + count - size / 8;
+ *max = count;
+ }
+ while (c) {
+ pair cdr = c -> cdr;
+ convert_num (s, (char *)(c -> car), base, size);
+ s -= size / 8;
+ /* Free up temp space. */
+ free (c -> car);
+ free (c);
+ c = cdr;
+ }
+ return bufp;
+}
+
+void convert_num (buf, str, base, size)
+ unsigned char *buf;
+ char *str;
+ int base;
+ int size;
+{
+ char *ptr = str;
+ int negative = 0;
+ u_int32_t val = 0;
+ int tval;
+ int max;
+
+ if (*ptr == '-') {
+ negative = 1;
+ ++ptr;
+ }
+
+ /* If base wasn't specified, figure it out from the data. */
+ if (!base) {
+ if (ptr [0] == '0') {
+ if (ptr [1] == 'x') {
+ base = 16;
+ ptr += 2;
+ } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
+ base = 8;
+ ptr += 1;
+ } else {
+ base = 10;
+ }
+ } else {
+ base = 10;
+ }
+ }
+
+ do {
+ tval = *ptr++;
+ /* XXX assumes ASCII... */
+ if (tval >= 'a')
+ tval = tval - 'a' + 10;
+ else if (tval >= 'A')
+ tval = tval - 'A' + 10;
+ else if (tval >= '0')
+ tval -= '0';
+ else {
+ warn ("Bogus number: %s.", str);
+ break;
+ }
+ if (tval >= base) {
+ warn ("Bogus number: %s: digit %d not in base %d\n",
+ str, tval, base);
+ break;
+ }
+ val = val * base + tval;
+ } while (*ptr);
+
+ if (negative)
+ max = (1 << (size - 1));
+ else
+ max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
+ if (val > max) {
+ switch (base) {
+ case 8:
+ warn ("value %s%o exceeds max (%d) for precision.",
+ negative ? "-" : "", val, max);
+ break;
+ case 16:
+ warn ("value %s%x exceeds max (%d) for precision.",
+ negative ? "-" : "", val, max);
+ break;
+ default:
+ warn ("value %s%u exceeds max (%d) for precision.",
+ negative ? "-" : "", val, max);
+ break;
+ }
+ }
+
+ if (negative) {
+ switch (size) {
+ case 8:
+ *buf = -(unsigned long)val;
+ break;
+ case 16:
+ putShort (buf, -(unsigned long)val);
+ break;
+ case 32:
+ putLong (buf, -(unsigned long)val);
+ break;
+ default:
+ warn ("Unexpected integer size: %d\n", size);
+ break;
+ }
+ } else {
+ switch (size) {
+ case 8:
+ *buf = (u_int8_t)val;
+ break;
+ case 16:
+ putUShort (buf, (u_int16_t)val);
+ break;
+ case 32:
+ putULong (buf, val);
+ break;
+ default:
+ warn ("Unexpected integer size: %d\n", size);
+ break;
+ }
+ }
+}
+
+/* date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
+ NUMBER COLON NUMBER COLON NUMBER SEMI
+
+ Dates are always in GMT; first number is day of week; next is
+ year/month/day; next is hours:minutes:seconds on a 24-hour
+ clock. */
+
+TIME parse_date (cfile)
+ FILE *cfile;
+{
+ struct tm tm;
+ int guess;
+ char *val;
+ int token;
+ static int months [11] = { 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334 };
+
+ /* Day of week... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric day of week expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_wday = atoi (val);
+
+ /* Year... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric year expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_year = atoi (val);
+ if (tm.tm_year > 1900)
+ tm.tm_year -= 1900;
+
+ /* Slash seperating year from month... */
+ token = next_token (&val, cfile);
+ if (token != SLASH) {
+ parse_warn ("expected slash seperating year from month.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+
+ /* Month... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric month expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_mon = atoi (val) - 1;
+
+ /* Slash seperating month from day... */
+ token = next_token (&val, cfile);
+ if (token != SLASH) {
+ parse_warn ("expected slash seperating month from day.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+
+ /* Month... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric day of month expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_mday = atoi (val);
+
+ /* Hour... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric hour expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_hour = atoi (val);
+
+ /* Colon seperating hour from minute... */
+ token = next_token (&val, cfile);
+ if (token != COLON) {
+ parse_warn ("expected colon seperating hour from minute.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+
+ /* Minute... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric minute expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_min = atoi (val);
+
+ /* Colon seperating minute from second... */
+ token = next_token (&val, cfile);
+ if (token != COLON) {
+ parse_warn ("expected colon seperating hour from minute.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+
+ /* Minute... */
+ token = next_token (&val, cfile);
+ if (token != NUMBER) {
+ parse_warn ("numeric minute expected.");
+ if (token != SEMI)
+ skip_to_semi (cfile);
+ return (TIME)0;
+ }
+ tm.tm_sec = atoi (val);
+ tm.tm_isdst = 0;
+
+ /* XXX */ /* We assume that mktime does not use tm_yday. */
+ tm.tm_yday = 0;
+
+ /* Make sure the date ends in a semicolon... */
+ token = next_token (&val, cfile);
+ if (token != SEMI) {
+ parse_warn ("semicolon expected.");
+ skip_to_semi (cfile);
+ return 0;
+ }
+
+ /* Guess the time value... */
+ guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */
+ (tm.tm_year - 69) / 4 + /* Leap days since '70 */
+ (tm.tm_mon /* Days in months this year */
+ ? months [tm.tm_mon - 1]
+ : 0) +
+ (tm.tm_mon > 1 && /* Leap day this year */
+ !((tm.tm_year - 72) & 3)) +
+ tm.tm_mday - 1) * 24) + /* Day of month */
+ tm.tm_hour) * 60) +
+ tm.tm_min) * 60) + tm.tm_sec;
+
+ /* This guess could be wrong because of leap seconds or other
+ weirdness we don't know about that the system does. For
+ now, we're just going to accept the guess, but at some point
+ it might be nice to do a successive approximation here to
+ get an exact value. Even if the error is small, if the
+ server is restarted frequently (and thus the lease database
+ is reread), the error could accumulate into something
+ significant. */
+
+ return guess;
+}
diff --git a/contrib/isc-dhcp/common/print.c b/contrib/isc-dhcp/common/print.c
new file mode 100644
index 000000000000..ed51b15841b1
--- /dev/null
+++ b/contrib/isc-dhcp/common/print.c
@@ -0,0 +1,184 @@
+/* print.c
+
+ Turn data structures into printable text. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: print.c,v 1.16.2.1 1998/06/25 21:11:31 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+char *print_hw_addr (htype, hlen, data)
+ int htype;
+ int hlen;
+ unsigned char *data;
+{
+ static char habuf [49];
+ char *s;
+ int i;
+
+ if (htype == 0 || hlen == 0) {
+ strcpy (habuf, "<null>");
+ } else {
+ s = habuf;
+ for (i = 0; i < hlen; i++) {
+ sprintf (s, "%02x", data [i]);
+ s += strlen (s);
+ *s++ = ':';
+ }
+ *--s = 0;
+ }
+ return habuf;
+}
+
+void print_lease (lease)
+ struct lease *lease;
+{
+ struct tm *t;
+ char tbuf [32];
+
+ debug (" Lease %s",
+ piaddr (lease -> ip_addr));
+
+ t = gmtime (&lease -> starts);
+ strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
+ debug (" start %s", tbuf);
+
+ t = gmtime (&lease -> ends);
+ strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
+ debug (" end %s", tbuf);
+
+ t = gmtime (&lease -> timestamp);
+ strftime (tbuf, sizeof tbuf, "%D %H:%M:%S", t);
+ debug (" stamp %s", tbuf);
+
+ debug (" hardware addr = %s",
+ print_hw_addr (lease -> hardware_addr.htype,
+ lease -> hardware_addr.hlen,
+ lease -> hardware_addr.haddr));
+ debug (" host %s ",
+ lease -> host ? lease -> host -> name : "<none>");
+}
+
+void dump_packet (tp)
+ struct packet *tp;
+{
+ struct dhcp_packet *tdp = tp -> raw;
+
+ debug ("packet length %d", tp -> packet_length);
+ debug ("op = %d htype = %d hlen = %d hops = %d",
+ tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
+ debug ("xid = %x secs = %d flags = %x",
+ tdp -> xid, tdp -> secs, tdp -> flags);
+ debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
+ debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
+ debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
+ debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
+ debug ("chaddr = %02.2x:%02.2x:%02.2x:%02.2x:%02.2x:%02.2x",
+ ((unsigned char *)(tdp -> chaddr)) [0],
+ ((unsigned char *)(tdp -> chaddr)) [1],
+ ((unsigned char *)(tdp -> chaddr)) [2],
+ ((unsigned char *)(tdp -> chaddr)) [3],
+ ((unsigned char *)(tdp -> chaddr)) [4],
+ ((unsigned char *)(tdp -> chaddr)) [5]);
+ debug ("filename = %s", tdp -> file);
+ debug ("server_name = %s", tdp -> sname);
+ if (tp -> options_valid) {
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ if (tp -> options [i].data)
+ debug (" %s = %s",
+ dhcp_options [i].name,
+ pretty_print_option
+ (i, tp -> options [i].data,
+ tp -> options [i].len, 1, 1));
+ }
+ }
+ debug ("");
+}
+
+void dump_raw (buf, len)
+ unsigned char *buf;
+ int len;
+{
+ int i;
+ char lbuf [80];
+ int lbix = 0;
+
+ lbuf [0] = 0;
+
+ for (i = 0; i < len; i++) {
+ if ((i & 15) == 0) {
+ if (lbix)
+ note (lbuf);
+ sprintf (lbuf, "%03x:", i);
+ lbix = 4;
+ } else if ((i & 7) == 0)
+ lbuf [lbix++] = ' ';
+ sprintf (&lbuf [lbix], " %02x", buf [i]);
+ lbix += 3;
+ }
+ note (lbuf);
+}
+
+void hash_dump (table)
+ struct hash_table *table;
+{
+ int i;
+ struct hash_bucket *bp;
+
+ if (!table)
+ return;
+
+ for (i = 0; i < table -> hash_count; i++) {
+ if (!table -> buckets [i])
+ continue;
+ note ("hash bucket %d:", i);
+ for (bp = table -> buckets [i]; bp; bp = bp -> next) {
+ if (bp -> len)
+ dump_raw (bp -> name, bp -> len);
+ else
+ note ((char *)bp -> name);
+ }
+ }
+}
diff --git a/contrib/isc-dhcp/common/raw.c b/contrib/isc-dhcp/common/raw.c
new file mode 100644
index 000000000000..973ede13b8f9
--- /dev/null
+++ b/contrib/isc-dhcp/common/raw.c
@@ -0,0 +1,132 @@
+/* socket.c
+
+ BSD raw socket interface code... */
+
+/* XXX
+
+ It's not clear how this should work, and that lack of clarity is
+ terribly detrimental to the NetBSD 1.1 kernel - it crashes and
+ burns.
+
+ Using raw sockets ought to be a big win over using BPF or something
+ like it, because you don't need to deal with the complexities of
+ the physical layer, but it appears not to be possible with existing
+ raw socket implementations. This may be worth revisiting in the
+ future. For now, this code can probably be considered a curiosity.
+ Sigh. */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''. */
+
+#ifndef lint
+static char copyright[] =
+"$Id: raw.c,v 1.11 1997/10/20 21:47:14 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+#if defined (USE_RAW_SEND)
+#include <sys/uio.h>
+
+/* Generic interface registration routine... */
+void if_register_send (info)
+ struct interface_info *info;
+{
+ struct sockaddr_in name;
+ int sock;
+ struct socklist *tmp;
+ int flag;
+
+ /* Set up the address we're going to connect to. */
+ name.sin_family = AF_INET;
+ name.sin_port = local_port;
+ name.sin_addr.s_addr = htonl (INADDR_BROADCAST);
+ memset (name.sin_zero, 0, sizeof (name.sin_zero));
+
+ /* List addresses on which we're listening. */
+ if (!quiet_interface_discovery)
+ note ("Sending on %s, port %d",
+ piaddr (info -> address), htons (local_port));
+ if ((sock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
+ error ("Can't create dhcp socket: %m");
+
+ /* Set the BROADCAST option so that we can broadcast DHCP responses. */
+ flag = 1;
+ if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
+ &flag, sizeof flag) < 0)
+ error ("Can't set SO_BROADCAST option on dhcp socket: %m");
+
+ /* Set the IP_HDRINCL flag so that we can supply our own IP
+ headers... */
+ if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &flag, sizeof flag) < 0)
+ error ("Can't set IP_HDRINCL flag: %m");
+
+ info -> wfdesc = sock;
+ if (!quiet_interface_discovery)
+ note ("Sending on Raw/%s/%s",
+ info -> name,
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+
+size_t send_packet (interface, packet, raw, len, from, to, hto)
+ struct interface_info *interface;
+ struct packet *packet;
+ struct dhcp_packet *raw;
+ size_t len;
+ struct in_addr from;
+ struct sockaddr_in *to;
+ struct hardware *hto;
+{
+ unsigned char buf [256];
+ int bufp = 0;
+ struct iovec iov [2];
+
+ /* Assemble the headers... */
+ assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
+ to -> sin_addr.s_addr, to -> sin_port,
+ (unsigned char *)raw, len);
+
+ /* Fire it off */
+ iov [0].iov_base = (char *)buf;
+ iov [0].iov_len = bufp;
+ iov [1].iov_base = (char *)raw;
+ iov [1].iov_len = len;
+
+ return writev(interface -> wfdesc, iov, 2);
+}
+#endif /* USE_SOCKET_SEND */
diff --git a/contrib/isc-dhcp/common/socket.c b/contrib/isc-dhcp/common/socket.c
new file mode 100644
index 000000000000..b317ff2ba255
--- /dev/null
+++ b/contrib/isc-dhcp/common/socket.c
@@ -0,0 +1,256 @@
+/* socket.c
+
+ BSD socket interface code... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+/* SO_BINDTODEVICE support added by Elliot Poger (poger@leland.stanford.edu).
+ * This sockopt allows a socket to be bound to a particular interface,
+ * thus enabling the use of DHCPD on a multihomed host.
+ * If SO_BINDTODEVICE is defined in your system header files, the use of
+ * this sockopt will be automatically enabled.
+ * I have implemented it under Linux; other systems should be doable also.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: socket.c,v 1.26.2.2 1998/06/25 21:11:32 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+#ifdef USE_SOCKET_FALLBACK
+# define USE_SOCKET_SEND
+# define if_register_send if_register_fallback
+# define send_packet send_fallback
+# define if_reinitialize_send if_reinitialize_fallback
+#endif
+
+static int once = 0;
+
+/* Reinitializes the specified interface after an address change. This
+ is not required for packet-filter APIs. */
+
+#ifdef USE_SOCKET_SEND
+void if_reinitialize_send (info)
+ struct interface_info *info;
+{
+#if 0
+#ifndef USE_SOCKET_RECEIVE
+ once = 0;
+ close (info -> wfdesc);
+#endif
+ if_register_send (info);
+#endif
+}
+#endif
+
+#ifdef USE_SOCKET_RECEIVE
+void if_reinitialize_receive (info)
+ struct interface_info *info;
+{
+#if 0
+ once = 0;
+ close (info -> rfdesc);
+ if_register_receive (info);
+#endif
+}
+#endif
+
+#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE)
+/* Generic interface registration routine... */
+int if_register_socket (info)
+ struct interface_info *info;
+{
+ struct sockaddr_in name;
+ int sock;
+ int flag;
+
+#ifndef SO_BINDTODEVICE
+ /* Make sure only one interface is registered. */
+ if (once)
+ error ("The standard socket API can only support %s",
+ "hosts with a single network interface.");
+ once = 1;
+#endif
+
+ /* Set up the address we're going to bind to. */
+ name.sin_family = AF_INET;
+ name.sin_port = local_port;
+ name.sin_addr.s_addr = INADDR_ANY;
+ memset (name.sin_zero, 0, sizeof (name.sin_zero));
+
+ /* Make a socket... */
+ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ error ("Can't create dhcp socket: %m");
+
+ /* Set the REUSEADDR option so that we don't fail to start if
+ we're being restarted. */
+ flag = 1;
+ if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&flag, sizeof flag) < 0)
+ error ("Can't set SO_REUSEADDR option on dhcp socket: %m");
+
+ /* Set the BROADCAST option so that we can broadcast DHCP responses. */
+ if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
+ (char *)&flag, sizeof flag) < 0)
+ error ("Can't set SO_BROADCAST option on dhcp socket: %m");
+
+ /* Bind the socket to this interface's IP address. */
+ if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0)
+ error ("Can't bind to dhcp address: %m");
+
+#ifdef SO_BINDTODEVICE
+ /* Bind this socket to this interface. */
+ if (setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE,
+ (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) {
+ error("setting SO_BINDTODEVICE");
+ }
+#endif
+
+ return sock;
+}
+#endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE */
+
+#ifdef USE_SOCKET_SEND
+void if_register_send (info)
+ struct interface_info *info;
+{
+#ifndef USE_SOCKET_RECEIVE
+ info -> wfdesc = if_register_socket (info);
+#else
+ info -> wfdesc = info -> rfdesc;
+#endif
+ if (!quiet_interface_discovery)
+ note ("Sending on Socket/%s/%s",
+ info -> name,
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+
+}
+#endif /* USE_SOCKET_SEND */
+
+#ifdef USE_SOCKET_RECEIVE
+void if_register_receive (info)
+ struct interface_info *info;
+{
+ /* If we're using the socket API for sending and receiving,
+ we don't need to register this interface twice. */
+ info -> rfdesc = if_register_socket (info);
+ if (!quiet_interface_discovery)
+ note ("Listening on Socket/%s/%s",
+ info -> name,
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_SOCKET_RECEIVE */
+
+#ifdef USE_SOCKET_SEND
+ssize_t send_packet (interface, packet, raw, len, from, to, hto)
+ struct interface_info *interface;
+ struct packet *packet;
+ struct dhcp_packet *raw;
+ size_t len;
+ struct in_addr from;
+ struct sockaddr_in *to;
+ struct hardware *hto;
+{
+ int result;
+#ifdef IGNORE_HOSTUNREACH
+ int retry = 0;
+ do {
+#endif
+ result = sendto (interface -> wfdesc, (char *)raw, len, 0,
+ (struct sockaddr *)to, sizeof *to);
+#ifdef IGNORE_HOSTUNREACH
+ } while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) &&
+ result < 0 &&
+ (errno == EHOSTUNREACH ||
+ errno == ECONNREFUSED) &&
+ retry++ < 10);
+#endif
+ return result;
+}
+#endif /* USE_SOCKET_SEND */
+
+#ifdef USE_SOCKET_RECEIVE
+ssize_t receive_packet (interface, buf, len, from, hfrom)
+ struct interface_info *interface;
+ unsigned char *buf;
+ size_t len;
+ struct sockaddr_in *from;
+ struct hardware *hfrom;
+{
+ int flen = sizeof *from;
+ int result;
+
+#ifdef IGNORE_HOSTUNREACH
+ int retry = 0;
+ do {
+#endif
+ result = recvfrom (interface -> rfdesc, (char *)buf, len, 0,
+ (struct sockaddr *)from, &flen);
+#ifdef IGNORE_HOSTUNREACH
+ } while (result < 0 &&
+ (errno == EHOSTUNREACH ||
+ errno == ECONNREFUSED) &&
+ retry++ < 10);
+#endif
+ return result;
+}
+#endif /* USE_SOCKET_RECEIVE */
+
+#ifdef USE_SOCKET_FALLBACK
+/* This just reads in a packet and silently discards it. */
+
+void fallback_discard (protocol)
+ struct protocol *protocol;
+{
+ char buf [1540];
+ struct sockaddr_in from;
+ int flen = sizeof from;
+ int status;
+ struct interface_info *interface = protocol -> local;
+
+ status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0,
+ (struct sockaddr *)&from, &flen);
+ if (status < 0)
+ warn ("fallback_discard: %m");
+}
+#endif /* USE_SOCKET_RECEIVE */
diff --git a/contrib/isc-dhcp/common/tables.c b/contrib/isc-dhcp/common/tables.c
new file mode 100644
index 000000000000..bdbba1b78d14
--- /dev/null
+++ b/contrib/isc-dhcp/common/tables.c
@@ -0,0 +1,692 @@
+/* tables.c
+
+ Tables of information... */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: tables.c,v 1.13.2.1 1998/06/25 21:11:32 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+/* DHCP Option names, formats and codes, from RFC1533.
+
+ Format codes:
+
+ e - end of data
+ I - IP address
+ l - 32-bit signed integer
+ L - 32-bit unsigned integer
+ s - 16-bit signed integer
+ S - 16-bit unsigned integer
+ b - 8-bit signed integer
+ B - 8-bit unsigned integer
+ t - ASCII text
+ f - flag (true or false)
+ A - array of whatever precedes (e.g., IA means array of IP addresses)
+*/
+
+struct universe dhcp_universe;
+struct option dhcp_options [256] = {
+ { "pad", "", &dhcp_universe, 0 },
+ { "subnet-mask", "I", &dhcp_universe, 1 },
+ { "time-offset", "l", &dhcp_universe, 2 },
+ { "routers", "IA", &dhcp_universe, 3 },
+ { "time-servers", "IA", &dhcp_universe, 4 },
+ { "ien116-name-servers", "IA", &dhcp_universe, 5 },
+ { "domain-name-servers", "IA", &dhcp_universe, 6 },
+ { "log-servers", "IA", &dhcp_universe, 7 },
+ { "cookie-servers", "IA", &dhcp_universe, 8 },
+ { "lpr-servers", "IA", &dhcp_universe, 9 },
+ { "impress-servers", "IA", &dhcp_universe, 10 },
+ { "resource-location-servers", "IA", &dhcp_universe, 11 },
+ { "host-name", "t", &dhcp_universe, 12 },
+ { "boot-size", "S", &dhcp_universe, 13 },
+ { "merit-dump", "t", &dhcp_universe, 14 },
+ { "domain-name", "t", &dhcp_universe, 15 },
+ { "swap-server", "I", &dhcp_universe, 16 },
+ { "root-path", "t", &dhcp_universe, 17 },
+ { "extensions-path", "t", &dhcp_universe, 18 },
+ { "ip-forwarding", "f", &dhcp_universe, 19 },
+ { "non-local-source-routing", "f", &dhcp_universe, 20 },
+ { "policy-filter", "IIA", &dhcp_universe, 21 },
+ { "max-dgram-reassembly", "S", &dhcp_universe, 22 },
+ { "default-ip-ttl", "B", &dhcp_universe, 23 },
+ { "path-mtu-aging-timeout", "L", &dhcp_universe, 24 },
+ { "path-mtu-plateau-table", "SA", &dhcp_universe, 25 },
+ { "interface-mtu", "S", &dhcp_universe, 26 },
+ { "all-subnets-local", "f", &dhcp_universe, 27 },
+ { "broadcast-address", "I", &dhcp_universe, 28 },
+ { "perform-mask-discovery", "f", &dhcp_universe, 29 },
+ { "mask-supplier", "f", &dhcp_universe, 30 },
+ { "router-discovery", "f", &dhcp_universe, 31 },
+ { "router-solicitation-address", "I", &dhcp_universe, 32 },
+ { "static-routes", "IIA", &dhcp_universe, 33 },
+ { "trailer-encapsulation", "f", &dhcp_universe, 34 },
+ { "arp-cache-timeout", "L", &dhcp_universe, 35 },
+ { "ieee802-3-encapsulation", "f", &dhcp_universe, 36 },
+ { "default-tcp-ttl", "B", &dhcp_universe, 37 },
+ { "tcp-keepalive-interval", "L", &dhcp_universe, 38 },
+ { "tcp-keepalive-garbage", "f", &dhcp_universe, 39 },
+ { "nis-domain", "t", &dhcp_universe, 40 },
+ { "nis-servers", "IA", &dhcp_universe, 41 },
+ { "ntp-servers", "IA", &dhcp_universe, 42 },
+ { "vendor-encapsulated-options", "X", &dhcp_universe, 43 },
+ { "netbios-name-servers", "IA", &dhcp_universe, 44 },
+ { "netbios-dd-server", "IA", &dhcp_universe, 45 },
+ { "netbios-node-type", "B", &dhcp_universe, 46 },
+ { "netbios-scope", "t", &dhcp_universe, 47 },
+ { "font-servers", "IA", &dhcp_universe, 48 },
+ { "x-display-manager", "IA", &dhcp_universe, 49 },
+ { "dhcp-requested-address", "I", &dhcp_universe, 50 },
+ { "dhcp-lease-time", "L", &dhcp_universe, 51 },
+ { "dhcp-option-overload", "B", &dhcp_universe, 52 },
+ { "dhcp-message-type", "B", &dhcp_universe, 53 },
+ { "dhcp-server-identifier", "I", &dhcp_universe, 54 },
+ { "dhcp-parameter-request-list", "BA", &dhcp_universe, 55 },
+ { "dhcp-message", "t", &dhcp_universe, 56 },
+ { "dhcp-max-message-size", "S", &dhcp_universe, 57 },
+ { "dhcp-renewal-time", "L", &dhcp_universe, 58 },
+ { "dhcp-rebinding-time", "L", &dhcp_universe, 59 },
+ { "dhcp-class-identifier", "t", &dhcp_universe, 60 },
+ { "dhcp-client-identifier", "X", &dhcp_universe, 61 },
+ { "option-62", "X", &dhcp_universe, 62 },
+ { "option-63", "X", &dhcp_universe, 63 },
+ { "option-64", "X", &dhcp_universe, 64 },
+ { "option-65", "X", &dhcp_universe, 65 },
+ { "option-66", "X", &dhcp_universe, 66 },
+ { "option-67", "X", &dhcp_universe, 67 },
+ { "option-68", "X", &dhcp_universe, 68 },
+ { "option-69", "X", &dhcp_universe, 69 },
+ { "option-70", "X", &dhcp_universe, 70 },
+ { "option-71", "X", &dhcp_universe, 71 },
+ { "option-72", "X", &dhcp_universe, 72 },
+ { "option-73", "X", &dhcp_universe, 73 },
+ { "option-74", "X", &dhcp_universe, 74 },
+ { "option-75", "X", &dhcp_universe, 75 },
+ { "option-76", "X", &dhcp_universe, 76 },
+ { "dhcp-user-class-identifier", "t", &dhcp_universe, 77 },
+ { "option-78", "X", &dhcp_universe, 78 },
+ { "option-79", "X", &dhcp_universe, 79 },
+ { "option-80", "X", &dhcp_universe, 80 },
+ { "option-81", "X", &dhcp_universe, 81 },
+ { "option-82", "X", &dhcp_universe, 82 },
+ { "option-83", "X", &dhcp_universe, 83 },
+ { "option-84", "X", &dhcp_universe, 84 },
+ { "nds-servers", "IA", &dhcp_universe, 85 },
+ { "nds-tree-name", "X", &dhcp_universe, 86 },
+ { "nds-context", "X", &dhcp_universe, 87 },
+ { "option-88", "X", &dhcp_universe, 88 },
+ { "option-89", "X", &dhcp_universe, 89 },
+ { "option-90", "X", &dhcp_universe, 90 },
+ { "option-91", "X", &dhcp_universe, 91 },
+ { "option-92", "X", &dhcp_universe, 92 },
+ { "option-93", "X", &dhcp_universe, 93 },
+ { "option-94", "X", &dhcp_universe, 94 },
+ { "option-95", "X", &dhcp_universe, 95 },
+ { "option-96", "X", &dhcp_universe, 96 },
+ { "option-97", "X", &dhcp_universe, 97 },
+ { "option-98", "X", &dhcp_universe, 98 },
+ { "option-99", "X", &dhcp_universe, 99 },
+ { "option-100", "X", &dhcp_universe, 100 },
+ { "option-101", "X", &dhcp_universe, 101 },
+ { "option-102", "X", &dhcp_universe, 102 },
+ { "option-103", "X", &dhcp_universe, 103 },
+ { "option-104", "X", &dhcp_universe, 104 },
+ { "option-105", "X", &dhcp_universe, 105 },
+ { "option-106", "X", &dhcp_universe, 106 },
+ { "option-107", "X", &dhcp_universe, 107 },
+ { "option-108", "X", &dhcp_universe, 108 },
+ { "option-109", "X", &dhcp_universe, 109 },
+ { "option-110", "X", &dhcp_universe, 110 },
+ { "option-111", "X", &dhcp_universe, 111 },
+ { "option-112", "X", &dhcp_universe, 112 },
+ { "option-113", "X", &dhcp_universe, 113 },
+ { "option-114", "X", &dhcp_universe, 114 },
+ { "option-115", "X", &dhcp_universe, 115 },
+ { "option-116", "X", &dhcp_universe, 116 },
+ { "option-117", "X", &dhcp_universe, 117 },
+ { "option-118", "X", &dhcp_universe, 118 },
+ { "option-119", "X", &dhcp_universe, 119 },
+ { "option-120", "X", &dhcp_universe, 120 },
+ { "option-121", "X", &dhcp_universe, 121 },
+ { "option-122", "X", &dhcp_universe, 122 },
+ { "option-123", "X", &dhcp_universe, 123 },
+ { "option-124", "X", &dhcp_universe, 124 },
+ { "option-125", "X", &dhcp_universe, 125 },
+ { "option-126", "X", &dhcp_universe, 126 },
+ { "option-127", "X", &dhcp_universe, 127 },
+ { "option-128", "X", &dhcp_universe, 128 },
+ { "option-129", "X", &dhcp_universe, 129 },
+ { "option-130", "X", &dhcp_universe, 130 },
+ { "option-131", "X", &dhcp_universe, 131 },
+ { "option-132", "X", &dhcp_universe, 132 },
+ { "option-133", "X", &dhcp_universe, 133 },
+ { "option-134", "X", &dhcp_universe, 134 },
+ { "option-135", "X", &dhcp_universe, 135 },
+ { "option-136", "X", &dhcp_universe, 136 },
+ { "option-137", "X", &dhcp_universe, 137 },
+ { "option-138", "X", &dhcp_universe, 138 },
+ { "option-139", "X", &dhcp_universe, 139 },
+ { "option-140", "X", &dhcp_universe, 140 },
+ { "option-141", "X", &dhcp_universe, 141 },
+ { "option-142", "X", &dhcp_universe, 142 },
+ { "option-143", "X", &dhcp_universe, 143 },
+ { "option-144", "X", &dhcp_universe, 144 },
+ { "option-145", "X", &dhcp_universe, 145 },
+ { "option-146", "X", &dhcp_universe, 146 },
+ { "option-147", "X", &dhcp_universe, 147 },
+ { "option-148", "X", &dhcp_universe, 148 },
+ { "option-149", "X", &dhcp_universe, 149 },
+ { "option-150", "X", &dhcp_universe, 150 },
+ { "option-151", "X", &dhcp_universe, 151 },
+ { "option-152", "X", &dhcp_universe, 152 },
+ { "option-153", "X", &dhcp_universe, 153 },
+ { "option-154", "X", &dhcp_universe, 154 },
+ { "option-155", "X", &dhcp_universe, 155 },
+ { "option-156", "X", &dhcp_universe, 156 },
+ { "option-157", "X", &dhcp_universe, 157 },
+ { "option-158", "X", &dhcp_universe, 158 },
+ { "option-159", "X", &dhcp_universe, 159 },
+ { "option-160", "X", &dhcp_universe, 160 },
+ { "option-161", "X", &dhcp_universe, 161 },
+ { "option-162", "X", &dhcp_universe, 162 },
+ { "option-163", "X", &dhcp_universe, 163 },
+ { "option-164", "X", &dhcp_universe, 164 },
+ { "option-165", "X", &dhcp_universe, 165 },
+ { "option-166", "X", &dhcp_universe, 166 },
+ { "option-167", "X", &dhcp_universe, 167 },
+ { "option-168", "X", &dhcp_universe, 168 },
+ { "option-169", "X", &dhcp_universe, 169 },
+ { "option-170", "X", &dhcp_universe, 170 },
+ { "option-171", "X", &dhcp_universe, 171 },
+ { "option-172", "X", &dhcp_universe, 172 },
+ { "option-173", "X", &dhcp_universe, 173 },
+ { "option-174", "X", &dhcp_universe, 174 },
+ { "option-175", "X", &dhcp_universe, 175 },
+ { "option-176", "X", &dhcp_universe, 176 },
+ { "option-177", "X", &dhcp_universe, 177 },
+ { "option-178", "X", &dhcp_universe, 178 },
+ { "option-179", "X", &dhcp_universe, 179 },
+ { "option-180", "X", &dhcp_universe, 180 },
+ { "option-181", "X", &dhcp_universe, 181 },
+ { "option-182", "X", &dhcp_universe, 182 },
+ { "option-183", "X", &dhcp_universe, 183 },
+ { "option-184", "X", &dhcp_universe, 184 },
+ { "option-185", "X", &dhcp_universe, 185 },
+ { "option-186", "X", &dhcp_universe, 186 },
+ { "option-187", "X", &dhcp_universe, 187 },
+ { "option-188", "X", &dhcp_universe, 188 },
+ { "option-189", "X", &dhcp_universe, 189 },
+ { "option-190", "X", &dhcp_universe, 190 },
+ { "option-191", "X", &dhcp_universe, 191 },
+ { "option-192", "X", &dhcp_universe, 192 },
+ { "option-193", "X", &dhcp_universe, 193 },
+ { "option-194", "X", &dhcp_universe, 194 },
+ { "option-195", "X", &dhcp_universe, 195 },
+ { "option-196", "X", &dhcp_universe, 196 },
+ { "option-197", "X", &dhcp_universe, 197 },
+ { "option-198", "X", &dhcp_universe, 198 },
+ { "option-199", "X", &dhcp_universe, 199 },
+ { "option-200", "X", &dhcp_universe, 200 },
+ { "option-201", "X", &dhcp_universe, 201 },
+ { "option-202", "X", &dhcp_universe, 202 },
+ { "option-203", "X", &dhcp_universe, 203 },
+ { "option-204", "X", &dhcp_universe, 204 },
+ { "option-205", "X", &dhcp_universe, 205 },
+ { "option-206", "X", &dhcp_universe, 206 },
+ { "option-207", "X", &dhcp_universe, 207 },
+ { "option-208", "X", &dhcp_universe, 208 },
+ { "option-209", "X", &dhcp_universe, 209 },
+ { "option-210", "X", &dhcp_universe, 210 },
+ { "option-211", "X", &dhcp_universe, 211 },
+ { "option-212", "X", &dhcp_universe, 212 },
+ { "option-213", "X", &dhcp_universe, 213 },
+ { "option-214", "X", &dhcp_universe, 214 },
+ { "option-215", "X", &dhcp_universe, 215 },
+ { "option-216", "X", &dhcp_universe, 216 },
+ { "option-217", "X", &dhcp_universe, 217 },
+ { "option-218", "X", &dhcp_universe, 218 },
+ { "option-219", "X", &dhcp_universe, 219 },
+ { "option-220", "X", &dhcp_universe, 220 },
+ { "option-221", "X", &dhcp_universe, 221 },
+ { "option-222", "X", &dhcp_universe, 222 },
+ { "option-223", "X", &dhcp_universe, 223 },
+ { "option-224", "X", &dhcp_universe, 224 },
+ { "option-225", "X", &dhcp_universe, 225 },
+ { "option-226", "X", &dhcp_universe, 226 },
+ { "option-227", "X", &dhcp_universe, 227 },
+ { "option-228", "X", &dhcp_universe, 228 },
+ { "option-229", "X", &dhcp_universe, 229 },
+ { "option-230", "X", &dhcp_universe, 230 },
+ { "option-231", "X", &dhcp_universe, 231 },
+ { "option-232", "X", &dhcp_universe, 232 },
+ { "option-233", "X", &dhcp_universe, 233 },
+ { "option-234", "X", &dhcp_universe, 234 },
+ { "option-235", "X", &dhcp_universe, 235 },
+ { "option-236", "X", &dhcp_universe, 236 },
+ { "option-237", "X", &dhcp_universe, 237 },
+ { "option-238", "X", &dhcp_universe, 238 },
+ { "option-239", "X", &dhcp_universe, 239 },
+ { "option-240", "X", &dhcp_universe, 240 },
+ { "option-241", "X", &dhcp_universe, 241 },
+ { "option-242", "X", &dhcp_universe, 242 },
+ { "option-243", "X", &dhcp_universe, 243 },
+ { "option-244", "X", &dhcp_universe, 244 },
+ { "option-245", "X", &dhcp_universe, 245 },
+ { "option-246", "X", &dhcp_universe, 246 },
+ { "option-247", "X", &dhcp_universe, 247 },
+ { "option-248", "X", &dhcp_universe, 248 },
+ { "option-249", "X", &dhcp_universe, 249 },
+ { "option-250", "X", &dhcp_universe, 250 },
+ { "option-251", "X", &dhcp_universe, 251 },
+ { "option-252", "X", &dhcp_universe, 252 },
+ { "option-253", "X", &dhcp_universe, 253 },
+ { "option-254", "X", &dhcp_universe, 254 },
+ { "option-end", "e", &dhcp_universe, 255 },
+};
+
+/* Default dhcp option priority list (this is ad hoc and should not be
+ mistaken for a carefully crafted and optimized list). */
+unsigned char dhcp_option_default_priority_list [] = {
+ DHO_DHCP_REQUESTED_ADDRESS,
+ DHO_DHCP_OPTION_OVERLOAD,
+ DHO_DHCP_MAX_MESSAGE_SIZE,
+ DHO_DHCP_RENEWAL_TIME,
+ DHO_DHCP_REBINDING_TIME,
+ DHO_DHCP_CLASS_IDENTIFIER,
+ DHO_DHCP_CLIENT_IDENTIFIER,
+ DHO_SUBNET_MASK,
+ DHO_TIME_OFFSET,
+ DHO_ROUTERS,
+ DHO_TIME_SERVERS,
+ DHO_NAME_SERVERS,
+ DHO_DOMAIN_NAME_SERVERS,
+ DHO_HOST_NAME,
+ DHO_LOG_SERVERS,
+ DHO_COOKIE_SERVERS,
+ DHO_LPR_SERVERS,
+ DHO_IMPRESS_SERVERS,
+ DHO_RESOURCE_LOCATION_SERVERS,
+ DHO_HOST_NAME,
+ DHO_BOOT_SIZE,
+ DHO_MERIT_DUMP,
+ DHO_DOMAIN_NAME,
+ DHO_SWAP_SERVER,
+ DHO_ROOT_PATH,
+ DHO_EXTENSIONS_PATH,
+ DHO_IP_FORWARDING,
+ DHO_NON_LOCAL_SOURCE_ROUTING,
+ DHO_POLICY_FILTER,
+ DHO_MAX_DGRAM_REASSEMBLY,
+ DHO_DEFAULT_IP_TTL,
+ DHO_PATH_MTU_AGING_TIMEOUT,
+ DHO_PATH_MTU_PLATEAU_TABLE,
+ DHO_INTERFACE_MTU,
+ DHO_ALL_SUBNETS_LOCAL,
+ DHO_BROADCAST_ADDRESS,
+ DHO_PERFORM_MASK_DISCOVERY,
+ DHO_MASK_SUPPLIER,
+ DHO_ROUTER_DISCOVERY,
+ DHO_ROUTER_SOLICITATION_ADDRESS,
+ DHO_STATIC_ROUTES,
+ DHO_TRAILER_ENCAPSULATION,
+ DHO_ARP_CACHE_TIMEOUT,
+ DHO_IEEE802_3_ENCAPSULATION,
+ DHO_DEFAULT_TCP_TTL,
+ DHO_TCP_KEEPALIVE_INTERVAL,
+ DHO_TCP_KEEPALIVE_GARBAGE,
+ DHO_NIS_DOMAIN,
+ DHO_NIS_SERVERS,
+ DHO_NTP_SERVERS,
+ DHO_VENDOR_ENCAPSULATED_OPTIONS,
+ DHO_NETBIOS_NAME_SERVERS,
+ DHO_NETBIOS_DD_SERVER,
+ DHO_NETBIOS_NODE_TYPE,
+ DHO_NETBIOS_SCOPE,
+ DHO_FONT_SERVERS,
+ DHO_X_DISPLAY_MANAGER,
+ DHO_DHCP_PARAMETER_REQUEST_LIST,
+
+ /* Presently-undefined options... */
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+ 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
+ 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
+ 251, 252, 253, 254,
+};
+
+int sizeof_dhcp_option_default_priority_list =
+ sizeof dhcp_option_default_priority_list;
+
+
+char *hardware_types [] = {
+ "unknown-0",
+ "ethernet",
+ "unknown-2",
+ "unknown-3",
+ "unknown-4",
+ "unknown-5",
+ "token-ring",
+ "unknown-7",
+ "unknown-8",
+ "unknown-9",
+ "unknown-10",
+ "unknown-11",
+ "unknown-12",
+ "unknown-13",
+ "unknown-14",
+ "unknown-15",
+ "unknown-16",
+ "unknown-17",
+ "unknown-18",
+ "unknown-19",
+ "unknown-20",
+ "unknown-21",
+ "unknown-22",
+ "unknown-23",
+ "unknown-24",
+ "unknown-25",
+ "unknown-26",
+ "unknown-27",
+ "unknown-28",
+ "unknown-29",
+ "unknown-30",
+ "unknown-31",
+ "unknown-32",
+ "unknown-33",
+ "unknown-34",
+ "unknown-35",
+ "unknown-36",
+ "unknown-37",
+ "unknown-38",
+ "unknown-39",
+ "unknown-40",
+ "unknown-41",
+ "unknown-42",
+ "unknown-43",
+ "unknown-44",
+ "unknown-45",
+ "unknown-46",
+ "unknown-47",
+ "unknown-48",
+ "unknown-49",
+ "unknown-50",
+ "unknown-51",
+ "unknown-52",
+ "unknown-53",
+ "unknown-54",
+ "unknown-55",
+ "unknown-56",
+ "unknown-57",
+ "unknown-58",
+ "unknown-59",
+ "unknown-60",
+ "unknown-61",
+ "unknown-62",
+ "unknown-63",
+ "unknown-64",
+ "unknown-65",
+ "unknown-66",
+ "unknown-67",
+ "unknown-68",
+ "unknown-69",
+ "unknown-70",
+ "unknown-71",
+ "unknown-72",
+ "unknown-73",
+ "unknown-74",
+ "unknown-75",
+ "unknown-76",
+ "unknown-77",
+ "unknown-78",
+ "unknown-79",
+ "unknown-80",
+ "unknown-81",
+ "unknown-82",
+ "unknown-83",
+ "unknown-84",
+ "unknown-85",
+ "unknown-86",
+ "unknown-87",
+ "unknown-88",
+ "unknown-89",
+ "unknown-90",
+ "unknown-91",
+ "unknown-92",
+ "unknown-93",
+ "unknown-94",
+ "unknown-95",
+ "unknown-96",
+ "unknown-97",
+ "unknown-98",
+ "unknown-99",
+ "unknown-100",
+ "unknown-101",
+ "unknown-102",
+ "unknown-103",
+ "unknown-104",
+ "unknown-105",
+ "unknown-106",
+ "unknown-107",
+ "unknown-108",
+ "unknown-109",
+ "unknown-110",
+ "unknown-111",
+ "unknown-112",
+ "unknown-113",
+ "unknown-114",
+ "unknown-115",
+ "unknown-116",
+ "unknown-117",
+ "unknown-118",
+ "unknown-119",
+ "unknown-120",
+ "unknown-121",
+ "unknown-122",
+ "unknown-123",
+ "unknown-124",
+ "unknown-125",
+ "unknown-126",
+ "unknown-127",
+ "unknown-128",
+ "unknown-129",
+ "unknown-130",
+ "unknown-131",
+ "unknown-132",
+ "unknown-133",
+ "unknown-134",
+ "unknown-135",
+ "unknown-136",
+ "unknown-137",
+ "unknown-138",
+ "unknown-139",
+ "unknown-140",
+ "unknown-141",
+ "unknown-142",
+ "unknown-143",
+ "unknown-144",
+ "unknown-145",
+ "unknown-146",
+ "unknown-147",
+ "unknown-148",
+ "unknown-149",
+ "unknown-150",
+ "unknown-151",
+ "unknown-152",
+ "unknown-153",
+ "unknown-154",
+ "unknown-155",
+ "unknown-156",
+ "unknown-157",
+ "unknown-158",
+ "unknown-159",
+ "unknown-160",
+ "unknown-161",
+ "unknown-162",
+ "unknown-163",
+ "unknown-164",
+ "unknown-165",
+ "unknown-166",
+ "unknown-167",
+ "unknown-168",
+ "unknown-169",
+ "unknown-170",
+ "unknown-171",
+ "unknown-172",
+ "unknown-173",
+ "unknown-174",
+ "unknown-175",
+ "unknown-176",
+ "unknown-177",
+ "unknown-178",
+ "unknown-179",
+ "unknown-180",
+ "unknown-181",
+ "unknown-182",
+ "unknown-183",
+ "unknown-184",
+ "unknown-185",
+ "unknown-186",
+ "unknown-187",
+ "unknown-188",
+ "unknown-189",
+ "unknown-190",
+ "unknown-191",
+ "unknown-192",
+ "unknown-193",
+ "unknown-194",
+ "unknown-195",
+ "unknown-196",
+ "unknown-197",
+ "unknown-198",
+ "unknown-199",
+ "unknown-200",
+ "unknown-201",
+ "unknown-202",
+ "unknown-203",
+ "unknown-204",
+ "unknown-205",
+ "unknown-206",
+ "unknown-207",
+ "unknown-208",
+ "unknown-209",
+ "unknown-210",
+ "unknown-211",
+ "unknown-212",
+ "unknown-213",
+ "unknown-214",
+ "unknown-215",
+ "unknown-216",
+ "unknown-217",
+ "unknown-218",
+ "unknown-219",
+ "unknown-220",
+ "unknown-221",
+ "unknown-222",
+ "unknown-223",
+ "unknown-224",
+ "unknown-225",
+ "unknown-226",
+ "unknown-227",
+ "unknown-228",
+ "unknown-229",
+ "unknown-230",
+ "unknown-231",
+ "unknown-232",
+ "unknown-233",
+ "unknown-234",
+ "unknown-235",
+ "unknown-236",
+ "unknown-237",
+ "unknown-238",
+ "unknown-239",
+ "unknown-240",
+ "unknown-241",
+ "unknown-242",
+ "unknown-243",
+ "unknown-244",
+ "unknown-245",
+ "unknown-246",
+ "unknown-247",
+ "unknown-248",
+ "unknown-249",
+ "unknown-250",
+ "unknown-251",
+ "unknown-252",
+ "unknown-253",
+ "unknown-254",
+ "unknown-255" };
+
+
+
+struct hash_table universe_hash;
+
+void initialize_universes()
+{
+ int i;
+
+ dhcp_universe.name = "dhcp";
+ dhcp_universe.hash = new_hash ();
+ if (!dhcp_universe.hash)
+ error ("Can't allocate dhcp option hash table.");
+ for (i = 0; i < 256; i++) {
+ dhcp_universe.options [i] = &dhcp_options [i];
+ add_hash (dhcp_universe.hash,
+ (unsigned char *)dhcp_options [i].name, 0,
+ (unsigned char *)&dhcp_options [i]);
+ }
+ universe_hash.hash_count = DEFAULT_HASH_SIZE;
+ add_hash (&universe_hash,
+ (unsigned char *)dhcp_universe.name, 0,
+ (unsigned char *)&dhcp_universe);
+}
diff --git a/contrib/isc-dhcp/common/tree.c b/contrib/isc-dhcp/common/tree.c
new file mode 100644
index 000000000000..ac83d67009ae
--- /dev/null
+++ b/contrib/isc-dhcp/common/tree.c
@@ -0,0 +1,412 @@
+/* tree.c
+
+ Routines for manipulating parse trees... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: tree.c,v 1.10 1997/05/09 08:14:57 mellon Exp $ Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+
+static TIME tree_evaluate_recurse PROTO ((int *, unsigned char **, int *,
+ struct tree *));
+static TIME do_host_lookup PROTO ((int *, unsigned char **, int *,
+ struct dns_host_entry *));
+static void do_data_copy PROTO ((int *, unsigned char **, int *,
+ unsigned char *, int));
+
+pair cons (car, cdr)
+ caddr_t car;
+ pair cdr;
+{
+ pair foo = (pair)dmalloc (sizeof *foo, "cons");
+ if (!foo)
+ error ("no memory for cons.");
+ foo -> car = car;
+ foo -> cdr = cdr;
+ return foo;
+}
+
+struct tree_cache *tree_cache (tree)
+ struct tree *tree;
+{
+ struct tree_cache *tc;
+
+ tc = new_tree_cache ("tree_cache");
+ if (!tc)
+ return 0;
+ tc -> value = (unsigned char *)0;
+ tc -> len = tc -> buf_size = 0;
+ tc -> timeout = 0;
+ tc -> tree = tree;
+ return tc;
+}
+
+struct tree *tree_host_lookup (name)
+ char *name;
+{
+ struct tree *nt;
+ nt = new_tree ("tree_host_lookup");
+ if (!nt)
+ error ("No memory for host lookup tree node.");
+ nt -> op = TREE_HOST_LOOKUP;
+ nt -> data.host_lookup.host = enter_dns_host (name);
+ return nt;
+}
+
+struct dns_host_entry *enter_dns_host (name)
+ char *name;
+{
+ struct dns_host_entry *dh;
+
+ if (!(dh = (struct dns_host_entry *)dmalloc
+ (sizeof (struct dns_host_entry), "enter_dns_host"))
+ || !(dh -> hostname = dmalloc (strlen (name) + 1,
+ "enter_dns_host")))
+ error ("Can't allocate space for new host.");
+ strcpy (dh -> hostname, name);
+ dh -> data = (unsigned char *)0;
+ dh -> data_len = 0;
+ dh -> buf_len = 0;
+ dh -> timeout = 0;
+ return dh;
+}
+
+struct tree *tree_const (data, len)
+ unsigned char *data;
+ int len;
+{
+ struct tree *nt;
+ if (!(nt = new_tree ("tree_const"))
+ || !(nt -> data.const_val.data =
+ (unsigned char *)dmalloc (len, "tree_const")))
+ error ("No memory for constant data tree node.");
+ nt -> op = TREE_CONST;
+ memcpy (nt -> data.const_val.data, data, len);
+ nt -> data.const_val.len = len;
+ return nt;
+}
+
+struct tree *tree_concat (left, right)
+ struct tree *left, *right;
+{
+ struct tree *nt;
+
+ /* If we're concatenating a null tree to a non-null tree, just
+ return the non-null tree; if both trees are null, return
+ a null tree. */
+ if (!left)
+ return right;
+ if (!right)
+ return left;
+
+ /* If both trees are constant, combine them. */
+ if (left -> op == TREE_CONST && right -> op == TREE_CONST) {
+ unsigned char *buf = dmalloc (left -> data.const_val.len
+ + right -> data.const_val.len,
+ "tree_concat");
+ if (!buf)
+ error ("No memory to concatenate constants.");
+ memcpy (buf, left -> data.const_val.data,
+ left -> data.const_val.len);
+ memcpy (buf + left -> data.const_val.len,
+ right -> data.const_val.data,
+ right -> data.const_val.len);
+ dfree (left -> data.const_val.data, "tree_concat");
+ dfree (right -> data.const_val.data, "tree_concat");
+ left -> data.const_val.data = buf;
+ left -> data.const_val.len += right -> data.const_val.len;
+ free_tree (right, "tree_concat");
+ return left;
+ }
+
+ /* Otherwise, allocate a new node to concatenate the two. */
+ if (!(nt = new_tree ("tree_concat")))
+ error ("No memory for data tree concatenation node.");
+ nt -> op = TREE_CONCAT;
+ nt -> data.concat.left = left;
+ nt -> data.concat.right = right;
+ return nt;
+}
+
+struct tree *tree_limit (tree, limit)
+ struct tree *tree;
+ int limit;
+{
+ struct tree *rv;
+
+ /* If the tree we're limiting is constant, limit it now. */
+ if (tree -> op == TREE_CONST) {
+ if (tree -> data.const_val.len > limit)
+ tree -> data.const_val.len = limit;
+ return tree;
+ }
+
+ /* Otherwise, put in a node which enforces the limit on evaluation. */
+ rv = new_tree ("tree_limit");
+ if (!rv)
+ return (struct tree *)0;
+ rv -> op = TREE_LIMIT;
+ rv -> data.limit.tree = tree;
+ rv -> data.limit.limit = limit;
+ return rv;
+}
+
+int tree_evaluate (tree_cache)
+ struct tree_cache *tree_cache;
+{
+ unsigned char *bp = tree_cache -> value;
+ int bc = tree_cache -> buf_size;
+ int bufix = 0;
+
+ /* If there's no tree associated with this cache, it evaluates
+ to a constant and that was detected at startup. */
+ if (!tree_cache -> tree)
+ return 1;
+
+ /* Try to evaluate the tree without allocating more memory... */
+ tree_cache -> timeout = tree_evaluate_recurse (&bufix, &bp, &bc,
+ tree_cache -> tree);
+
+ /* No additional allocation needed? */
+ if (bufix <= bc) {
+ tree_cache -> len = bufix;
+ return 1;
+ }
+
+ /* If we can't allocate more memory, return with what we
+ have (maybe nothing). */
+ if (!(bp = (unsigned char *)dmalloc (bufix, "tree_evaluate")))
+ return 0;
+
+ /* Record the change in conditions... */
+ bc = bufix;
+ bufix = 0;
+
+ /* Note that the size of the result shouldn't change on the
+ second call to tree_evaluate_recurse, since we haven't
+ changed the ``current'' time. */
+ tree_evaluate_recurse (&bufix, &bp, &bc, tree_cache -> tree);
+
+ /* Free the old buffer if needed, then store the new buffer
+ location and size and return. */
+ if (tree_cache -> value)
+ dfree (tree_cache -> value, "tree_evaluate");
+ tree_cache -> value = bp;
+ tree_cache -> len = bufix;
+ tree_cache -> buf_size = bc;
+ return 1;
+}
+
+static TIME tree_evaluate_recurse (bufix, bufp, bufcount, tree)
+ int *bufix;
+ unsigned char **bufp;
+ int *bufcount;
+ struct tree *tree;
+{
+ int limit;
+ TIME t1, t2;
+
+ switch (tree -> op) {
+ case TREE_CONCAT:
+ t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+ tree -> data.concat.left);
+ t2 = tree_evaluate_recurse (bufix, bufp, bufcount,
+ tree -> data.concat.right);
+ if (t1 > t2)
+ return t2;
+ return t1;
+
+ case TREE_HOST_LOOKUP:
+ return do_host_lookup (bufix, bufp, bufcount,
+ tree -> data.host_lookup.host);
+
+ case TREE_CONST:
+ do_data_copy (bufix, bufp, bufcount,
+ tree -> data.const_val.data,
+ tree -> data.const_val.len);
+ t1 = MAX_TIME;
+ return t1;
+
+ case TREE_LIMIT:
+ limit = *bufix + tree -> data.limit.limit;
+ t1 = tree_evaluate_recurse (bufix, bufp, bufcount,
+ tree -> data.limit.tree);
+ *bufix = limit;
+ return t1;
+
+ default:
+ warn ("Bad node id in tree: %d.");
+ t1 = MAX_TIME;
+ return t1;
+ }
+}
+
+static TIME do_host_lookup (bufix, bufp, bufcount, dns)
+ int *bufix;
+ unsigned char **bufp;
+ int *bufcount;
+ struct dns_host_entry *dns;
+{
+ struct hostent *h;
+ int i;
+ int new_len;
+
+#ifdef DEBUG_EVAL
+ debug ("time: now = %d dns = %d %d diff = %d",
+ cur_time, dns -> timeout, cur_time - dns -> timeout);
+#endif
+
+ /* If the record hasn't timed out, just copy the data and return. */
+ if (cur_time <= dns -> timeout) {
+#ifdef DEBUG_EVAL
+ debug ("easy copy: %x %d %x",
+ dns -> data, dns -> data_len,
+ dns -> data ? *(int *)(dns -> data) : 0);
+#endif
+ do_data_copy (bufix, bufp, bufcount,
+ dns -> data, dns -> data_len);
+ return dns -> timeout;
+ }
+#ifdef DEBUG_EVAL
+ debug ("Looking up %s", dns -> hostname);
+#endif
+
+ /* Otherwise, look it up... */
+ h = gethostbyname (dns -> hostname);
+ if (!h) {
+#ifndef NO_H_ERRNO
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+#endif
+ warn ("%s: host unknown.", dns -> hostname);
+#ifndef NO_H_ERRNO
+ break;
+ case TRY_AGAIN:
+ warn ("%s: temporary name server failure",
+ dns -> hostname);
+ break;
+ case NO_RECOVERY:
+ warn ("%s: name server failed", dns -> hostname);
+ break;
+ case NO_DATA:
+ warn ("%s: no A record associated with address",
+ dns -> hostname);
+ }
+#endif /* !NO_H_ERRNO */
+
+ /* Okay to try again after a minute. */
+ return cur_time + 60;
+ }
+
+#ifdef DEBUG_EVAL
+ debug ("Lookup succeeded; first address is %x",
+ h -> h_addr_list [0]);
+#endif
+
+ /* Count the number of addresses we got... */
+ for (i = 0; h -> h_addr_list [i]; i++)
+ ;
+
+ /* Do we need to allocate more memory? */
+ new_len = i * h -> h_length;
+ if (dns -> buf_len < i) {
+ unsigned char *buf =
+ (unsigned char *)dmalloc (new_len, "do_host_lookup");
+ /* If we didn't get more memory, use what we have. */
+ if (!buf) {
+ new_len = dns -> buf_len;
+ if (!dns -> buf_len) {
+ dns -> timeout = cur_time + 60;
+ return dns -> timeout;
+ }
+ } else {
+ if (dns -> data)
+ dfree (dns -> data, "do_host_lookup");
+ dns -> data = buf;
+ dns -> buf_len = new_len;
+ }
+ }
+
+ /* Addresses are conveniently stored one to the buffer, so we
+ have to copy them out one at a time... :'( */
+ for (i = 0; i < new_len / h -> h_length; i++) {
+ memcpy (dns -> data + h -> h_length * i,
+ h -> h_addr_list [i], h -> h_length);
+ }
+#ifdef DEBUG_EVAL
+ debug ("dns -> data: %x h -> h_addr_list [0]: %x",
+ *(int *)(dns -> data), h -> h_addr_list [0]);
+#endif
+ dns -> data_len = new_len;
+
+ /* Set the timeout for an hour from now.
+ XXX This should really use the time on the DNS reply. */
+ dns -> timeout = cur_time + 3600;
+
+#ifdef DEBUG_EVAL
+ debug ("hard copy: %x %d %x",
+ dns -> data, dns -> data_len, *(int *)(dns -> data));
+#endif
+ do_data_copy (bufix, bufp, bufcount, dns -> data, dns -> data_len);
+ return dns -> timeout;
+}
+
+static void do_data_copy (bufix, bufp, bufcount, data, len)
+ int *bufix;
+ unsigned char **bufp;
+ int *bufcount;
+ unsigned char *data;
+ int len;
+{
+ int space = *bufcount - *bufix;
+
+ /* If there's more space than we need, use only what we need. */
+ if (space > len)
+ space = len;
+
+ /* Copy as much data as will fit, then increment the buffer index
+ by the amount we actually had to copy, which could be more. */
+ if (space > 0)
+ memcpy (*bufp + *bufix, data, space);
+ *bufix += len;
+}
diff --git a/contrib/isc-dhcp/common/upf.c b/contrib/isc-dhcp/common/upf.c
new file mode 100644
index 000000000000..498b6e6cde1b
--- /dev/null
+++ b/contrib/isc-dhcp/common/upf.c
@@ -0,0 +1,298 @@
+/* upf.c
+
+ Ultrix PacketFilter interface code.
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef lint
+static char copyright[] =
+"$Id: upf.c,v 1.3 1997/10/20 21:47:15 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
+#endif /* not lint */
+
+#include "dhcpd.h"
+#if defined (USE_UPF_SEND) || defined (USE_UPF_RECEIVE)
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#include <net/pfilt.h>
+#include <netinet/in_systm.h>
+#include "includes/netinet/ip.h"
+#include "includes/netinet/udp.h"
+#include "includes/netinet/if_ether.h"
+
+/* Reinitializes the specified interface after an address change. This
+ is not required for packet-filter APIs. */
+
+#ifdef USE_UPF_SEND
+void if_reinitialize_send (info)
+ struct interface_info *info;
+{
+}
+#endif
+
+#ifdef USE_UPF_RECEIVE
+void if_reinitialize_receive (info)
+ struct interface_info *info;
+{
+}
+#endif
+
+/* Called by get_interface_list for each interface that's discovered.
+ Opens a packet filter for each interface and adds it to the select
+ mask. */
+
+int if_register_upf (info)
+ struct interface_info *info;
+{
+ int sock;
+ char filename[50];
+ int b;
+ struct endevp param;
+
+ /* Open a UPF device */
+ for (b = 0; 1; b++) {
+#ifndef NO_SNPRINTF
+ snprintf(filename, sizeof(filename), "/dev/pf/pfilt%d", b);
+#else
+ sprintf(filename, "/dev/pf/pfilt%d", b);
+#endif
+ sock = open (filename, O_RDWR, 0);
+ if (sock < 0) {
+ if (errno == EBUSY) {
+ continue;
+ } else {
+ error ("Can't find free upf: %m");
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* Set the UPF device to point at this interface. */
+ if (ioctl (sock, EIOCSETIF, info -> ifp) < 0)
+ error ("Can't attach interface %s to upf device %s: %m",
+ info -> name, filename);
+
+ /* Get the hardware address. */
+ if (ioctl (sock, EIOCDEVP, &param) < 0)
+ error ("Can't get interface %s hardware address: %m",
+ info -> name);
+
+ /* We only know how to do ethernet. */
+ if (param.end_dev_type != ENDT_10MB)
+ error ("Invalid device type on network interface %s: %d",
+ info -> name, param.end_dev_type);
+
+ if (param.end_addr_len != 6)
+ error ("Invalid hardware address length on %s: %d",
+ info -> name, param.end_addr_len);
+
+ info -> hw_address.hlen = 6;
+ info -> hw_address.htype = ARPHRD_ETHER;
+ memcpy (&info -> hw_address.haddr [0], param.end_addr, 6);
+
+ return sock;
+}
+#endif /* USE_UPF_SEND || USE_UPF_RECEIVE */
+
+#ifdef USE_UPF_SEND
+void if_register_send (info)
+ struct interface_info *info;
+{
+ /* If we're using the upf API for sending and receiving,
+ we don't need to register this interface twice. */
+#ifndef USE_UPF_RECEIVE
+ info -> wfdesc = if_register_upf (info, interface);
+#else
+ info -> wfdesc = info -> rfdesc;
+#endif
+ if (!quiet_interface_discovery)
+ note ("Sending on UPF/%s/%s/%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_UPF_SEND */
+
+#ifdef USE_UPF_RECEIVE
+/* Packet filter program...
+ XXX Changes to the filter program may require changes to the constant
+ offsets used in if_register_send to patch the UPF program! XXX */
+
+
+void if_register_receive (info)
+ struct interface_info *info;
+{
+ int flag = 1;
+ u_int32_t addr;
+ struct enfilter pf;
+ u_int32_t bits;
+
+ /* Open a UPF device and hang it on this interface... */
+ info -> rfdesc = if_register_upf (info);
+
+ /* Allow the copyall flag to be set... */
+ if (ioctl(info -> rfdesc, EIOCALLOWCOPYALL, &flag) < 0)
+ error ("Can't set ALLOWCOPYALL: %m");
+
+ /* Clear all the packet filter mode bits first... */
+ flag = (ENHOLDSIG | ENBATCH | ENTSTAMP | ENPROMISC |
+ ENNONEXCL | ENCOPYALL);
+ if (ioctl (info -> rfdesc, EIOCMBIC, &flag) < 0)
+ error ("Can't clear pfilt bits: %m");
+
+ /* Set the ENBATCH and ENCOPYALL bits... */
+ bits = ENBATCH | ENCOPYALL;
+ if (ioctl (info -> rfdesc, EIOCMBIS, &bits) < 0)
+ error ("Can't set ENBATCH|ENCOPYALL: %m");
+
+ /* Set up the UPF filter program. */
+ /* XXX Unlike the BPF filter program, this one won't work if the
+ XXX IP packet is fragmented or if there are options on the IP
+ XXX header. */
+ pf.enf_Priority = 0;
+ pf.enf_FilterLen = 0;
+
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 6;
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
+ pf.enf_Filter [pf.enf_FilterLen++] = htons (ETHERTYPE_IP);
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT;
+ pf.enf_Filter [pf.enf_FilterLen++] = htons (IPPROTO_UDP);
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 11;
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_AND;
+ pf.enf_Filter [pf.enf_FilterLen++] = htons (0xFF);
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_CAND;
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHWORD + 18;
+ pf.enf_Filter [pf.enf_FilterLen++] = ENF_PUSHLIT + ENF_CAND;
+ pf.enf_Filter [pf.enf_FilterLen++] = local_port;
+
+ if (ioctl (info -> rfdesc, EIOCSETF, &pf) < 0)
+ error ("Can't install packet filter program: %m");
+ if (!quiet_interface_discovery)
+ note ("Listening on UPF/%s/%s/%s",
+ info -> name,
+ print_hw_addr (info -> hw_address.htype,
+ info -> hw_address.hlen,
+ info -> hw_address.haddr),
+ (info -> shared_network ?
+ info -> shared_network -> name : "unattached"));
+}
+#endif /* USE_UPF_RECEIVE */
+
+#ifdef USE_UPF_SEND
+ssize_t send_packet (interface, packet, raw, len, from, to, hto)
+ struct interface_info *interface;
+ struct packet *packet;
+ struct dhcp_packet *raw;
+ size_t len;
+ struct in_addr from;
+ struct sockaddr_in *to;
+ struct hardware *hto;
+{
+ int bufp = 0;
+ unsigned char buf [256];
+ struct iovec iov [2];
+
+ /* Assemble the headers... */
+ assemble_hw_header (interface, buf, &bufp, hto);
+ assemble_udp_ip_header (interface, buf, &bufp, from.s_addr,
+ to -> sin_addr.s_addr, to -> sin_port,
+ (unsigned char *)raw, len);
+
+ /* Fire it off */
+ iov [0].iov_base = (char *)buf;
+ iov [0].iov_len = bufp;
+ iov [1].iov_base = (char *)raw;
+ iov [1].iov_len = len;
+
+ return writev(interface -> wfdesc, iov, 2);
+}
+#endif /* USE_UPF_SEND */
+
+#ifdef USE_UPF_RECEIVE
+ssize_t receive_packet (interface, buf, len, from, hfrom)
+ struct interface_info *interface;
+ unsigned char *buf;
+ size_t len;
+ struct sockaddr_in *from;
+ struct hardware *hfrom;
+{
+ int nread;
+ int length = 0;
+ int offset = 0;
+ unsigned char ibuf [1500 + sizeof (struct enstamp)];
+ int bufix = 0;
+
+ length = read (interface -> rfdesc, ibuf, sizeof ibuf);
+ if (length <= 0)
+ return length;
+
+ bufix = sizeof (struct enstamp);
+ /* Decode the physical header... */
+ offset = decode_hw_header (interface, ibuf, bufix, hfrom);
+
+ /* If a physical layer checksum failed (dunno of any
+ physical layer that supports this, but WTH), skip this
+ packet. */
+ if (offset < 0) {
+ return 0;
+ }
+
+ bufix += offset;
+ length -= offset;
+
+ /* Decode the IP and UDP headers... */
+ offset = decode_udp_ip_header (interface, ibuf, bufix,
+ from, (unsigned char *)0, length);
+
+ /* If the IP or UDP checksum was bad, skip the packet... */
+ if (offset < 0)
+ return 0;
+
+ bufix += offset;
+ length -= offset;
+
+ /* Copy out the data in the packet... */
+ memcpy (buf, &ibuf [bufix], length);
+ return length;
+}
+#endif
diff --git a/contrib/isc-dhcp/includes/arpa/nameser.h b/contrib/isc-dhcp/includes/arpa/nameser.h
new file mode 100644
index 000000000000..5b38997aba01
--- /dev/null
+++ b/contrib/isc-dhcp/includes/arpa/nameser.h
@@ -0,0 +1,237 @@
+/*
+ * ++Copyright++ 1983, 1989, 1993
+ * -
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * @(#)nameser.h 8.1 (Berkeley) 6/2/93
+ * $Id: nameser.h,v 8.3 1995/08/21 01:27:12 vixie Exp
+ */
+
+#ifndef _NAMESER_H_
+#define _NAMESER_H_
+
+/*
+ * Define constants based on rfc883
+ */
+#define PACKETSZ 512 /* maximum packet size */
+#define MAXDNAME 256 /* maximum domain name */
+#define MAXCDNAME 255 /* maximum compressed domain name */
+#define MAXLABEL 63 /* maximum length of domain label */
+#define HFIXEDSZ 12 /* #/bytes of fixed data in header */
+#define QFIXEDSZ 4 /* #/bytes of fixed data in query */
+#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
+#define INT32SZ 4 /* for systems without 32-bit ints */
+#define INT16SZ 2 /* for systems without 16-bit ints */
+#define INADDRSZ 4 /* for sizeof(struct inaddr) != 4 */
+
+/*
+ * Internet nameserver port number
+ */
+#define NAMESERVER_PORT 53
+
+/*
+ * Currently defined opcodes
+ */
+#define QUERY 0x0 /* standard query */
+#define IQUERY 0x1 /* inverse query */
+#define STATUS 0x2 /* nameserver status query */
+/*#define xxx 0x3*/ /* 0x3 reserved */
+#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */
+#ifdef ALLOW_UPDATES
+ /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */
+# define UPDATEA 0x9 /* add resource record */
+# define UPDATED 0xa /* delete a specific resource record */
+# define UPDATEDA 0xb /* delete all named resource record */
+# define UPDATEM 0xc /* modify a specific resource record */
+# define UPDATEMA 0xd /* modify all named resource record */
+# define ZONEINIT 0xe /* initial zone transfer */
+# define ZONEREF 0xf /* incremental zone referesh */
+#endif
+
+/*
+ * Currently defined response codes
+ */
+#define NOERROR 0 /* no error */
+#define FORMERR 1 /* format error */
+#define SERVFAIL 2 /* server failure */
+#define NXDOMAIN 3 /* non existent domain */
+#define NOTIMP 4 /* not implemented */
+#define REFUSED 5 /* query refused */
+#ifdef ALLOW_UPDATES
+ /* non standard */
+# define NOCHANGE 0xf /* update failed to change db */
+#endif
+
+/*
+ * Type values for resources and queries
+ */
+#define T_A 1 /* host address */
+#define T_NS 2 /* authoritative server */
+#define T_MD 3 /* mail destination */
+#define T_MF 4 /* mail forwarder */
+#define T_CNAME 5 /* canonical name */
+#define T_SOA 6 /* start of authority zone */
+#define T_MB 7 /* mailbox domain name */
+#define T_MG 8 /* mail group member */
+#define T_MR 9 /* mail rename name */
+#define T_NULL 10 /* null resource record */
+#define T_WKS 11 /* well known service */
+#define T_PTR 12 /* domain name pointer */
+#define T_HINFO 13 /* host information */
+#define T_MINFO 14 /* mailbox information */
+#define T_MX 15 /* mail routing information */
+#define T_TXT 16 /* text strings */
+#define T_RP 17 /* responsible person */
+#define T_AFSDB 18 /* AFS cell database */
+#define T_X25 19 /* X_25 calling address */
+#define T_ISDN 20 /* ISDN calling address */
+#define T_RT 21 /* router */
+#define T_NSAP 22 /* NSAP address */
+#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */
+#define T_SIG 24 /* security signature */
+#define T_KEY 25 /* security key */
+#define T_PX 26 /* X.400 mail mapping */
+#define T_GPOS 27 /* geographical position (withdrawn) */
+#define T_AAAA 28 /* IP6 Address */
+#define T_LOC 29 /* Location Information */
+ /* non standard */
+#define T_UINFO 100 /* user (finger) information */
+#define T_UID 101 /* user ID */
+#define T_GID 102 /* group ID */
+#define T_UNSPEC 103 /* Unspecified format (binary data) */
+ /* Query type values which do not appear in resource records */
+#define T_AXFR 252 /* transfer zone of authority */
+#define T_MAILB 253 /* transfer mailbox records */
+#define T_MAILA 254 /* transfer mail agent records */
+#define T_ANY 255 /* wildcard match */
+
+/*
+ * Values for class field
+ */
+
+#define C_IN 1 /* the arpa internet */
+#define C_CHAOS 3 /* for chaos net (MIT) */
+#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */
+ /* Query class values which do not appear in resource records */
+#define C_ANY 255 /* wildcard match */
+
+/*
+ * Status return codes for T_UNSPEC conversion routines
+ */
+#define CONV_SUCCESS 0
+#define CONV_OVERFLOW (-1)
+#define CONV_BADFMT (-2)
+#define CONV_BADCKSUM (-3)
+#define CONV_BADBUFLEN (-4)
+
+/*
+ * Structure for query header. The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields. We use bit fields only in int variables, as this
+ * is all ANSI requires. This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+ unsigned id :16; /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+ /* fields in third byte */
+ unsigned qr: 1; /* response flag */
+ unsigned opcode: 4; /* purpose of message */
+ unsigned aa: 1; /* authoritive answer */
+ unsigned tc: 1; /* truncated message */
+ unsigned rd: 1; /* recursion desired */
+ /* fields in fourth byte */
+ unsigned ra: 1; /* recursion available */
+ unsigned pr:1; /* primary server required (non standard) */
+ unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */
+ unsigned rcode :4; /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+ /* fields in third byte */
+ unsigned rd :1; /* recursion desired */
+ unsigned tc :1; /* truncated message */
+ unsigned aa :1; /* authoritive answer */
+ unsigned opcode :4; /* purpose of message */
+ unsigned qr :1; /* response flag */
+ /* fields in fourth byte */
+ unsigned rcode :4; /* response code */
+ unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */
+ unsigned pr:1; /* primary server required (non standard) */
+ unsigned ra :1; /* recursion available */
+#endif
+ /* remaining bytes */
+ unsigned qdcount :16; /* number of question entries */
+ unsigned ancount :16; /* number of answer entries */
+ unsigned nscount :16; /* number of authority entries */
+ unsigned arcount :16; /* number of resource entries */
+} HEADER;
+
+/*
+ * Defines for handling compressed domain names
+ */
+#define INDIR_MASK 0xc0
+
+/*
+ * Structure for passing resource records around.
+ */
+struct rrec {
+ int16_t r_zone; /* zone number */
+ int16_t r_class; /* class number */
+ int16_t r_type; /* type number */
+ u_int32_t r_ttl; /* time to live */
+ int r_size; /* size of data area */
+ char *r_data; /* pointer to data */
+};
+
+#endif /* !_NAMESER_H_ */
diff --git a/contrib/isc-dhcp/includes/cdefs.h b/contrib/isc-dhcp/includes/cdefs.h
new file mode 100644
index 000000000000..2bc67a5251a9
--- /dev/null
+++ b/contrib/isc-dhcp/includes/cdefs.h
@@ -0,0 +1,57 @@
+/* cdefs.h
+
+ Standard C definitions... */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium.
+ * All Rights Reserved.
+ * Copyright (c) 1995 RadioMail Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of RadioMail Corporation, the Internet Software
+ * Consortium nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY RADIOMAIL CORPORATION, THE INTERNET
+ * SOFTWARE CONSORTIUM AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL RADIOMAIL CORPORATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises. Further modifications have
+ * been made for the Internet Software Consortium under a contract
+ * with Vixie Laboratories.
+ */
+
+#if (defined (__GNUC__) || defined (__STDC__)) && !defined (BROKEN_ANSI)
+#define PROTO(x) x
+#define KandR(x)
+#define ANSI_DECL(x) x
+#if defined (__GNUC__)
+#define INLINE inline
+#else
+#define INLINE
+#endif /* __GNUC__ */
+#else
+#define PROTO(x) ()
+#define KandR(x) x
+#define ANSI_DECL(x)
+#define INLINE
+#endif /* __GNUC__ || __STDC__ */
diff --git a/contrib/isc-dhcp/includes/cf/freebsd.h b/contrib/isc-dhcp/includes/cf/freebsd.h
new file mode 100644
index 000000000000..965d33236f23
--- /dev/null
+++ b/contrib/isc-dhcp/includes/cf/freebsd.h
@@ -0,0 +1,89 @@
+/* freebsd.h
+
+ System dependencies for FreeBSD... */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE INTERNET SOFTWARE CONSORTIUM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software was written for the Internet Software Consortium by Ted Lemon
+ * under a contract with Vixie Laboratories.
+ */
+
+#define _ANSI_SOURCE
+
+#include <syslog.h>
+#include <sys/types.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <limits.h>
+
+#include <sys/wait.h>
+#include <signal.h>
+
+extern int h_errno;
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#define INADDR_LOOPBACK ((u_int32_t)0x7f000001)
+
+/* Varargs stuff... */
+#include <stdarg.h>
+#define VA_DOTDOTDOT ...
+#define va_dcl
+#define VA_start(list, last) va_start (list, last)
+
+#ifndef _PATH_DHCPD_PID
+#define _PATH_DHCPD_PID "/var/run/dhcpd.pid"
+#endif
+#ifndef _PATH_DHCPD_DB
+#define _PATH_DHCPD_DB "/var/db/dhcpd.leases"
+#endif
+#ifndef _PATH_DHCLIENT_PID
+#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid"
+#endif
+#ifndef _PATH_DHCLIENT_DB
+#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases"
+#endif
+
+#define EOL '\n'
+#define VOIDPTR void *
+
+/* Time stuff... */
+#include <sys/time.h>
+#define TIME time_t
+#define GET_TIME(x) time ((x))
+
+#define HAVE_SA_LEN
+
+#if defined (USE_DEFAULT_NETWORK)
+# define USE_BPF
+#endif
diff --git a/contrib/isc-dhcp/includes/dhcp.h b/contrib/isc-dhcp/includes/dhcp.h
new file mode 100644
index 000000000000..181277579527
--- /dev/null
+++ b/contrib/isc-dhcp/includes/dhcp.h
@@ -0,0 +1,167 @@
+/* dhcp.h
+
+ Protocol structures... */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \
+ 20 + /* IP header */ \
+ 8) /* UDP header */
+#define DHCP_SNAME_LEN 64
+#define DHCP_FILE_LEN 128
+#define DHCP_FIXED_NON_UDP 236
+#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
+ /* Everything but options. */
+#define DHCP_MTU_MAX 1500
+#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
+
+#define BOOTP_MIN_LEN 300
+#define DHCP_MIN_LEN 548
+
+struct dhcp_packet {
+ u_int8_t op; /* Message opcode/type */
+ u_int8_t htype; /* Hardware addr type (see net/if_types.h) */
+ u_int8_t hlen; /* Hardware addr length */
+ u_int8_t hops; /* Number of relay agent hops from client */
+ u_int32_t xid; /* Transaction ID */
+ u_int16_t secs; /* Seconds since client started looking */
+ u_int16_t flags; /* Flag bits */
+ struct in_addr ciaddr; /* Client IP address (if already in use) */
+ struct in_addr yiaddr; /* Client IP address */
+ struct in_addr siaddr; /* IP address of next server to talk to */
+ struct in_addr giaddr; /* DHCP relay agent IP address */
+ unsigned char chaddr [16]; /* Client hardware address */
+ char sname [DHCP_SNAME_LEN]; /* Server name */
+ char file [DHCP_FILE_LEN]; /* Boot filename */
+ unsigned char options [DHCP_OPTION_LEN];
+ /* Optional parameters
+ (actual length dependent on MTU). */
+};
+
+/* BOOTP (rfc951) message types */
+#define BOOTREQUEST 1
+#define BOOTREPLY 2
+
+/* Possible values for flags field... */
+#define BOOTP_BROADCAST 32768L
+
+/* Possible values for hardware type (htype) field... */
+#define HTYPE_ETHER 1 /* Ethernet 10Mbps */
+#define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */
+
+/* Magic cookie validating dhcp options field (and bootp vendor
+ extensions field). */
+#define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+
+/* DHCP Option codes: */
+
+#define DHO_PAD 0
+#define DHO_SUBNET_MASK 1
+#define DHO_TIME_OFFSET 2
+#define DHO_ROUTERS 3
+#define DHO_TIME_SERVERS 4
+#define DHO_NAME_SERVERS 5
+#define DHO_DOMAIN_NAME_SERVERS 6
+#define DHO_LOG_SERVERS 7
+#define DHO_COOKIE_SERVERS 8
+#define DHO_LPR_SERVERS 9
+#define DHO_IMPRESS_SERVERS 10
+#define DHO_RESOURCE_LOCATION_SERVERS 11
+#define DHO_HOST_NAME 12
+#define DHO_BOOT_SIZE 13
+#define DHO_MERIT_DUMP 14
+#define DHO_DOMAIN_NAME 15
+#define DHO_SWAP_SERVER 16
+#define DHO_ROOT_PATH 17
+#define DHO_EXTENSIONS_PATH 18
+#define DHO_IP_FORWARDING 19
+#define DHO_NON_LOCAL_SOURCE_ROUTING 20
+#define DHO_POLICY_FILTER 21
+#define DHO_MAX_DGRAM_REASSEMBLY 22
+#define DHO_DEFAULT_IP_TTL 23
+#define DHO_PATH_MTU_AGING_TIMEOUT 24
+#define DHO_PATH_MTU_PLATEAU_TABLE 25
+#define DHO_INTERFACE_MTU 26
+#define DHO_ALL_SUBNETS_LOCAL 27
+#define DHO_BROADCAST_ADDRESS 28
+#define DHO_PERFORM_MASK_DISCOVERY 29
+#define DHO_MASK_SUPPLIER 30
+#define DHO_ROUTER_DISCOVERY 31
+#define DHO_ROUTER_SOLICITATION_ADDRESS 32
+#define DHO_STATIC_ROUTES 33
+#define DHO_TRAILER_ENCAPSULATION 34
+#define DHO_ARP_CACHE_TIMEOUT 35
+#define DHO_IEEE802_3_ENCAPSULATION 36
+#define DHO_DEFAULT_TCP_TTL 37
+#define DHO_TCP_KEEPALIVE_INTERVAL 38
+#define DHO_TCP_KEEPALIVE_GARBAGE 39
+#define DHO_NIS_DOMAIN 40
+#define DHO_NIS_SERVERS 41
+#define DHO_NTP_SERVERS 42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
+#define DHO_NETBIOS_NAME_SERVERS 44
+#define DHO_NETBIOS_DD_SERVER 45
+#define DHO_NETBIOS_NODE_TYPE 46
+#define DHO_NETBIOS_SCOPE 47
+#define DHO_FONT_SERVERS 48
+#define DHO_X_DISPLAY_MANAGER 49
+#define DHO_DHCP_REQUESTED_ADDRESS 50
+#define DHO_DHCP_LEASE_TIME 51
+#define DHO_DHCP_OPTION_OVERLOAD 52
+#define DHO_DHCP_MESSAGE_TYPE 53
+#define DHO_DHCP_SERVER_IDENTIFIER 54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
+#define DHO_DHCP_MESSAGE 56
+#define DHO_DHCP_MAX_MESSAGE_SIZE 57
+#define DHO_DHCP_RENEWAL_TIME 58
+#define DHO_DHCP_REBINDING_TIME 59
+#define DHO_DHCP_CLASS_IDENTIFIER 60
+#define DHO_DHCP_CLIENT_IDENTIFIER 61
+#define DHO_DHCP_USER_CLASS_ID 77
+#define DHO_END 255
+
+/* DHCP message types. */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
diff --git a/contrib/isc-dhcp/includes/dhcpd.h b/contrib/isc-dhcp/includes/dhcpd.h
new file mode 100644
index 000000000000..cf82132bc74b
--- /dev/null
+++ b/contrib/isc-dhcp/includes/dhcpd.h
@@ -0,0 +1,947 @@
+/* dhcpd.h
+
+ Definitions for dhcpd... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#ifndef __CYGWIN32__
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#else
+#define fd_set cygwin_fd_set
+#include <sys/types.h>
+#endif
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "cdefs.h"
+#include "osdep.h"
+#include "dhcp.h"
+#include "tree.h"
+#include "hash.h"
+#include "inet.h"
+#include "sysconf.h"
+
+struct option_data {
+ int len;
+ u_int8_t *data;
+};
+
+struct string_list {
+ struct string_list *next;
+ char string [1];
+};
+
+/* A name server, from /etc/resolv.conf. */
+struct name_server {
+ struct name_server *next;
+ struct sockaddr_in addr;
+ TIME rcdate;
+};
+
+/* A domain search list element. */
+struct domain_search_list {
+ struct domain_search_list *next;
+ char *domain;
+ TIME rcdate;
+};
+
+/* A dhcp packet and the pointers to its option values. */
+struct packet {
+ struct dhcp_packet *raw;
+ int packet_length;
+ int packet_type;
+ int options_valid;
+ int client_port;
+ struct iaddr client_addr;
+ struct interface_info *interface; /* Interface on which packet
+ was received. */
+ struct hardware *haddr; /* Physical link address
+ of local sender (maybe gateway). */
+ struct shared_network *shared_network;
+ struct option_data options [256];
+};
+
+struct hardware {
+ u_int8_t htype;
+ u_int8_t hlen;
+ u_int8_t haddr [16];
+};
+
+/* A dhcp lease declaration structure. */
+struct lease {
+ struct lease *next;
+ struct lease *prev;
+ struct lease *n_uid, *n_hw;
+ struct lease *waitq_next;
+
+ struct iaddr ip_addr;
+ TIME starts, ends, timestamp;
+ unsigned char *uid;
+ int uid_len;
+ int uid_max;
+ unsigned char uid_buf [32];
+ char *hostname;
+ char *client_hostname;
+ struct host_decl *host;
+ struct subnet *subnet;
+ struct shared_network *shared_network;
+ struct hardware hardware_addr;
+
+ int flags;
+# define STATIC_LEASE 1
+# define BOOTP_LEASE 2
+# define DYNAMIC_BOOTP_OK 4
+# define PERSISTENT_FLAGS (DYNAMIC_BOOTP_OK)
+# define EPHEMERAL_FLAGS (BOOTP_LEASE)
+# define MS_NULL_TERMINATION 8
+# define ABANDONED_LEASE 16
+
+ struct lease_state *state;
+};
+
+struct lease_state {
+ struct lease_state *next;
+
+ struct interface_info *ip;
+
+ TIME offered_expiry;
+
+ struct tree_cache *options [256];
+ u_int32_t expiry, renewal, rebind;
+ char *filename, *server_name;
+
+ u_int32_t xid;
+ u_int16_t secs;
+ u_int16_t bootp_flags;
+ struct in_addr ciaddr;
+ struct in_addr giaddr;
+ u_int8_t hops;
+ u_int8_t offer;
+};
+
+#define ROOT_GROUP 0
+#define HOST_DECL 1
+#define SHARED_NET_DECL 2
+#define SUBNET_DECL 3
+#define CLASS_DECL 4
+#define GROUP_DECL 5
+
+/* Possible modes in which discover_interfaces can run. */
+
+#define DISCOVER_RUNNING 0
+#define DISCOVER_SERVER 1
+#define DISCOVER_UNCONFIGURED 2
+#define DISCOVER_RELAY 3
+#define DISCOVER_REQUESTED 4
+
+/* Group of declarations that share common parameters. */
+struct group {
+ struct group *next;
+
+ struct subnet *subnet;
+ struct shared_network *shared_network;
+
+ TIME default_lease_time;
+ TIME max_lease_time;
+ TIME bootp_lease_cutoff;
+ TIME bootp_lease_length;
+
+ char *filename;
+ char *server_name;
+ struct iaddr next_server;
+
+ int boot_unknown_clients;
+ int dynamic_bootp;
+ int allow_bootp;
+ int allow_booting;
+ int one_lease_per_client;
+ int get_lease_hostnames;
+ int use_host_decl_names;
+
+ struct tree_cache *options [256];
+};
+
+/* A dhcp host declaration structure. */
+struct host_decl {
+ struct host_decl *n_ipaddr;
+ char *name;
+ struct hardware interface;
+ struct tree_cache *fixed_addr;
+ struct group *group;
+};
+
+struct shared_network {
+ struct shared_network *next;
+ char *name;
+ struct subnet *subnets;
+ struct interface_info *interface;
+ struct lease *leases;
+ struct lease *insertion_point;
+ struct lease *last_lease;
+
+ struct group *group;
+};
+
+struct subnet {
+ struct subnet *next_subnet;
+ struct subnet *next_sibling;
+ struct shared_network *shared_network;
+ struct interface_info *interface;
+ struct iaddr interface_address;
+ struct iaddr net;
+ struct iaddr netmask;
+
+ struct group *group;
+};
+
+struct class {
+ char *name;
+
+ struct group *group;
+};
+
+/* DHCP client lease structure... */
+struct client_lease {
+ struct client_lease *next; /* Next lease in list. */
+ TIME expiry, renewal, rebind; /* Lease timeouts. */
+ struct iaddr address; /* Address being leased. */
+ char *server_name; /* Name of boot server. */
+ char *filename; /* Name of file we're supposed to boot. */
+ struct string_list *medium; /* Network medium. */
+
+ unsigned int is_static : 1; /* If set, lease is from config file. */
+ unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */
+
+ struct option_data options [256]; /* Options supplied with lease. */
+};
+
+/* Possible states in which the client can be. */
+enum dhcp_state {
+ S_REBOOTING,
+ S_INIT,
+ S_SELECTING,
+ S_REQUESTING,
+ S_BOUND,
+ S_RENEWING,
+ S_REBINDING
+};
+
+/* Configuration information from the config file... */
+struct client_config {
+ struct option_data defaults [256]; /* Default values for options. */
+ enum {
+ ACTION_DEFAULT, /* Use server value if present,
+ otherwise default. */
+ ACTION_SUPERSEDE, /* Always use default. */
+ ACTION_PREPEND, /* Prepend default to server. */
+ ACTION_APPEND, /* Append default to server. */
+ } default_actions [256];
+
+ struct option_data send_options [256]; /* Send these to server. */
+ u_int8_t required_options [256]; /* Options server must supply. */
+ u_int8_t requested_options [256]; /* Options to request from server. */
+ int requested_option_count; /* Number of requested options. */
+ TIME timeout; /* Start to panic if we don't get a
+ lease in this time period when
+ SELECTING. */
+ TIME initial_interval; /* All exponential backoff intervals
+ start here. */
+ TIME retry_interval; /* If the protocol failed to produce
+ an address before the timeout,
+ try the protocol again after this
+ many seconds. */
+ TIME select_interval; /* Wait this many seconds from the
+ first DHCPDISCOVER before
+ picking an offered lease. */
+ TIME reboot_timeout; /* When in INIT-REBOOT, wait this
+ long before giving up and going
+ to INIT. */
+ TIME backoff_cutoff; /* When doing exponential backoff,
+ never back off to an interval
+ longer than this amount. */
+ struct string_list *media; /* Possible network media values. */
+ char *script_name; /* Name of config script. */
+ enum { IGNORE, ACCEPT, PREFER } bootp_policy;
+ /* Ignore, accept or prefer BOOTP
+ responses. */
+ struct string_list *medium; /* Current network medium. */
+
+ struct iaddrlist *reject_list; /* Servers to reject. */
+};
+
+/* Per-interface state used in the dhcp client... */
+struct client_state {
+ struct client_lease *active; /* Currently active lease. */
+ struct client_lease *new; /* New lease. */
+ struct client_lease *offered_leases; /* Leases offered to us. */
+ struct client_lease *leases; /* Leases we currently hold. */
+ struct client_lease *alias; /* Alias lease. */
+
+ enum dhcp_state state; /* Current state for this interface. */
+ struct iaddr destination; /* Where to send packet. */
+ u_int32_t xid; /* Transaction ID. */
+ TIME first_sending; /* When was first copy sent? */
+ TIME interval; /* What's the current resend interval? */
+ struct string_list *medium; /* Last media type tried. */
+
+ struct dhcp_packet packet; /* Outgoing DHCP packet. */
+ int packet_length; /* Actual length of generated packet. */
+
+ struct iaddr requested_address; /* Address we would like to get. */
+
+ struct client_config *config; /* Information from config file. */
+};
+
+/* Information about each network interface. */
+
+struct interface_info {
+ struct interface_info *next; /* Next interface in list... */
+ struct shared_network *shared_network;
+ /* Networks connected to this interface. */
+ struct hardware hw_address; /* Its physical address. */
+ struct in_addr primary_address; /* Primary interface address. */
+ char name [IFNAMSIZ]; /* Its name... */
+ int rfdesc; /* Its read file descriptor. */
+ int wfdesc; /* Its write file descriptor, if
+ different. */
+ unsigned char *rbuf; /* Read buffer, if required. */
+ size_t rbuf_max; /* Size of read buffer. */
+ size_t rbuf_offset; /* Current offset into buffer. */
+ size_t rbuf_len; /* Length of data in buffer. */
+
+ struct ifreq *ifp; /* Pointer to ifreq struct. */
+ u_int32_t flags; /* Control flags... */
+#define INTERFACE_REQUESTED 1
+#define INTERFACE_AUTOMATIC 2
+
+ /* Only used by DHCP client code. */
+ struct client_state *client;
+};
+
+struct hardware_link {
+ struct hardware_link *next;
+ char name [IFNAMSIZ];
+ struct hardware address;
+};
+
+struct timeout {
+ struct timeout *next;
+ TIME when;
+ void (*func) PROTO ((void *));
+ void *what;
+};
+
+struct protocol {
+ struct protocol *next;
+ int fd;
+ void (*handler) PROTO ((struct protocol *));
+ void *local;
+};
+
+/* Bitmask of dhcp option codes. */
+typedef unsigned char option_mask [16];
+
+/* DHCP Option mask manipulation macros... */
+#define OPTION_ZERO(mask) (memset (mask, 0, 16))
+#define OPTION_SET(mask, bit) (mask [bit >> 8] |= (1 << (bit & 7)))
+#define OPTION_CLR(mask, bit) (mask [bit >> 8] &= ~(1 << (bit & 7)))
+#define OPTION_ISSET(mask, bit) (mask [bit >> 8] & (1 << (bit & 7)))
+#define OPTION_ISCLR(mask, bit) (!OPTION_ISSET (mask, bit))
+
+/* An option occupies its length plus two header bytes (code and
+ length) for every 255 bytes that must be stored. */
+#define OPTION_SPACE(x) ((x) + 2 * ((x) / 255 + 1))
+
+/* Default path to dhcpd config file. */
+#ifdef DEBUG
+#undef _PATH_DHCPD_CONF
+#define _PATH_DHCPD_CONF "dhcpd.conf"
+#undef _PATH_DHCPD_DB
+#define _PATH_DHCPD_DB "dhcpd.leases"
+#else
+#ifndef _PATH_DHCPD_CONF
+#define _PATH_DHCPD_CONF "/etc/dhcpd.conf"
+#endif
+
+#ifndef _PATH_DHCPD_DB
+#define _PATH_DHCPD_DB "/etc/dhcpd.leases"
+#endif
+
+#ifndef _PATH_DHCPD_PID
+#define _PATH_DHCPD_PID "/var/run/dhcpd.pid"
+#endif
+#endif
+
+#ifndef _PATH_DHCLIENT_CONF
+#define _PATH_DHCLIENT_CONF "/etc/dhclient.conf"
+#endif
+
+#ifndef _PATH_DHCLIENT_PID
+#define _PATH_DHCLIENT_PID "/var/run/dhclient.pid"
+#endif
+
+#ifndef _PATH_DHCLIENT_DB
+#define _PATH_DHCLIENT_DB "/etc/dhclient.leases"
+#endif
+
+#ifndef _PATH_RESOLV_CONF
+#define _PATH_RESOLV_CONF "/etc/resolv.conf"
+#endif
+
+#ifndef _PATH_DHCRELAY_PID
+#define _PATH_DHCRELAY_PID "/var/run/dhcrelay.pid"
+#endif
+
+#ifndef DHCPD_LOG_FACILITY
+#define DHCPD_LOG_FACILITY LOG_DAEMON
+#endif
+
+#define MAX_TIME 0x7fffffff
+#define MIN_TIME 0
+
+/* External definitions... */
+
+/* options.c */
+
+void parse_options PROTO ((struct packet *));
+void parse_option_buffer PROTO ((struct packet *, unsigned char *, int));
+int cons_options PROTO ((struct packet *, struct dhcp_packet *,
+ struct tree_cache **, int, int, int));
+int store_options PROTO ((unsigned char *, int, struct tree_cache **,
+ unsigned char *, int, int, int, int));
+char *pretty_print_option PROTO ((unsigned int,
+ unsigned char *, int, int, int));
+void do_packet PROTO ((struct interface_info *,
+ struct dhcp_packet *, int,
+ unsigned int, struct iaddr, struct hardware *));
+
+/* errwarn.c */
+extern int warnings_occurred;
+void error PROTO ((char *, ...));
+int warn PROTO ((char *, ...));
+int note PROTO ((char *, ...));
+int debug PROTO ((char *, ...));
+int parse_warn PROTO ((char *, ...));
+
+/* dhcpd.c */
+extern TIME cur_time;
+extern struct group root_group;
+
+extern u_int16_t local_port;
+extern u_int16_t remote_port;
+extern int log_priority;
+extern int log_perror;
+
+#ifdef USE_FALLBACK
+extern struct interface_info fallback_interface;
+#endif
+
+extern char *path_dhcpd_conf;
+extern char *path_dhcpd_db;
+extern char *path_dhcpd_pid;
+
+int main PROTO ((int, char **, char **));
+void cleanup PROTO ((void));
+void lease_pinged PROTO ((struct iaddr, u_int8_t *, int));
+void lease_ping_timeout PROTO ((void *));
+
+/* conflex.c */
+extern int lexline, lexchar;
+extern char *token_line, *tlname;
+extern char comments [4096];
+extern int comment_index;
+extern int eol_token;
+void new_parse PROTO ((char *));
+int next_token PROTO ((char **, FILE *));
+int peek_token PROTO ((char **, FILE *));
+
+/* confpars.c */
+int readconf PROTO ((void));
+void read_leases PROTO ((void));
+int parse_statement PROTO ((FILE *,
+ struct group *, int, struct host_decl *, int));
+void parse_allow_deny PROTO ((FILE *, struct group *, int));
+void skip_to_semi PROTO ((FILE *));
+int parse_boolean PROTO ((FILE *));
+int parse_semi PROTO ((FILE *));
+int parse_lbrace PROTO ((FILE *));
+void parse_host_declaration PROTO ((FILE *, struct group *));
+char *parse_host_name PROTO ((FILE *));
+void parse_class_declaration PROTO ((FILE *, struct group *, int));
+void parse_lease_time PROTO ((FILE *, TIME *));
+void parse_shared_net_declaration PROTO ((FILE *, struct group *));
+void parse_subnet_declaration PROTO ((FILE *, struct shared_network *));
+void parse_group_declaration PROTO ((FILE *, struct group *));
+void parse_hardware_param PROTO ((FILE *, struct hardware *));
+char *parse_string PROTO ((FILE *));
+struct tree *parse_ip_addr_or_hostname PROTO ((FILE *, int));
+struct tree_cache *parse_fixed_addr_param PROTO ((FILE *));
+void parse_option_param PROTO ((FILE *, struct group *));
+TIME parse_timestamp PROTO ((FILE *));
+struct lease *parse_lease_declaration PROTO ((FILE *));
+void parse_address_range PROTO ((FILE *, struct subnet *));
+TIME parse_date PROTO ((FILE *));
+unsigned char *parse_numeric_aggregate PROTO ((FILE *,
+ unsigned char *, int *,
+ int, int, int));
+void convert_num PROTO ((unsigned char *, char *, int, int));
+
+/* tree.c */
+pair cons PROTO ((caddr_t, pair));
+struct tree_cache *tree_cache PROTO ((struct tree *));
+struct tree *tree_host_lookup PROTO ((char *));
+struct dns_host_entry *enter_dns_host PROTO ((char *));
+struct tree *tree_const PROTO ((unsigned char *, int));
+struct tree *tree_concat PROTO ((struct tree *, struct tree *));
+struct tree *tree_limit PROTO ((struct tree *, int));
+int tree_evaluate PROTO ((struct tree_cache *));
+
+/* dhcp.c */
+extern int outstanding_pings;
+
+void dhcp PROTO ((struct packet *));
+void dhcpdiscover PROTO ((struct packet *));
+void dhcprequest PROTO ((struct packet *));
+void dhcprelease PROTO ((struct packet *));
+void dhcpdecline PROTO ((struct packet *));
+void dhcpinform PROTO ((struct packet *));
+void nak_lease PROTO ((struct packet *, struct iaddr *cip));
+void ack_lease PROTO ((struct packet *, struct lease *, unsigned int, TIME));
+void dhcp_reply PROTO ((struct lease *));
+struct lease *find_lease PROTO ((struct packet *,
+ struct shared_network *, int *));
+struct lease *mockup_lease PROTO ((struct packet *,
+ struct shared_network *,
+ struct host_decl *));
+
+/* bootp.c */
+void bootp PROTO ((struct packet *));
+
+/* memory.c */
+void enter_host PROTO ((struct host_decl *));
+struct host_decl *find_hosts_by_haddr PROTO ((int, unsigned char *, int));
+struct host_decl *find_hosts_by_uid PROTO ((unsigned char *, int));
+struct subnet *find_host_for_network PROTO ((struct host_decl **,
+ struct iaddr *,
+ struct shared_network *));
+void new_address_range PROTO ((struct iaddr, struct iaddr,
+ struct subnet *, int));
+extern struct subnet *find_grouped_subnet PROTO ((struct shared_network *,
+ struct iaddr));
+extern struct subnet *find_subnet PROTO ((struct iaddr));
+void enter_shared_network PROTO ((struct shared_network *));
+void enter_subnet PROTO ((struct subnet *));
+void enter_lease PROTO ((struct lease *));
+int supersede_lease PROTO ((struct lease *, struct lease *, int));
+void release_lease PROTO ((struct lease *));
+void abandon_lease PROTO ((struct lease *, char *));
+struct lease *find_lease_by_uid PROTO ((unsigned char *, int));
+struct lease *find_lease_by_hw_addr PROTO ((unsigned char *, int));
+struct lease *find_lease_by_ip_addr PROTO ((struct iaddr));
+void uid_hash_add PROTO ((struct lease *));
+void uid_hash_delete PROTO ((struct lease *));
+void hw_hash_add PROTO ((struct lease *));
+void hw_hash_delete PROTO ((struct lease *));
+struct class *add_class PROTO ((int, char *));
+struct class *find_class PROTO ((int, unsigned char *, int));
+struct group *clone_group PROTO ((struct group *, char *));
+void write_leases PROTO ((void));
+void dump_subnets PROTO ((void));
+
+/* alloc.c */
+VOIDPTR dmalloc PROTO ((int, char *));
+void dfree PROTO ((VOIDPTR, char *));
+struct packet *new_packet PROTO ((char *));
+struct dhcp_packet *new_dhcp_packet PROTO ((char *));
+struct tree *new_tree PROTO ((char *));
+struct tree_cache *new_tree_cache PROTO ((char *));
+struct hash_table *new_hash_table PROTO ((int, char *));
+struct hash_bucket *new_hash_bucket PROTO ((char *));
+struct lease *new_lease PROTO ((char *));
+struct lease *new_leases PROTO ((int, char *));
+struct subnet *new_subnet PROTO ((char *));
+struct class *new_class PROTO ((char *));
+struct shared_network *new_shared_network PROTO ((char *));
+struct group *new_group PROTO ((char *));
+struct protocol *new_protocol PROTO ((char *));
+struct lease_state *new_lease_state PROTO ((char *));
+struct domain_search_list *new_domain_search_list PROTO ((char *));
+struct name_server *new_name_server PROTO ((char *));
+void free_name_server PROTO ((struct name_server *, char *));
+void free_domain_search_list PROTO ((struct domain_search_list *, char *));
+void free_lease_state PROTO ((struct lease_state *, char *));
+void free_protocol PROTO ((struct protocol *, char *));
+void free_group PROTO ((struct group *, char *));
+void free_shared_network PROTO ((struct shared_network *, char *));
+void free_class PROTO ((struct class *, char *));
+void free_subnet PROTO ((struct subnet *, char *));
+void free_lease PROTO ((struct lease *, char *));
+void free_hash_bucket PROTO ((struct hash_bucket *, char *));
+void free_hash_table PROTO ((struct hash_table *, char *));
+void free_tree_cache PROTO ((struct tree_cache *, char *));
+void free_packet PROTO ((struct packet *, char *));
+void free_dhcp_packet PROTO ((struct dhcp_packet *, char *));
+void free_tree PROTO ((struct tree *, char *));
+
+/* print.c */
+char *print_hw_addr PROTO ((int, int, unsigned char *));
+void print_lease PROTO ((struct lease *));
+void dump_raw PROTO ((unsigned char *, int));
+void dump_packet PROTO ((struct packet *));
+void hash_dump PROTO ((struct hash_table *));
+
+/* socket.c */
+#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \
+ || defined (USE_SOCKET_FALLBACK)
+int if_register_socket PROTO ((struct interface_info *));
+#endif
+
+#ifdef USE_SOCKET_FALLBACK
+void if_reinitialize_fallback PROTO ((struct interface_info *));
+void if_register_fallback PROTO ((struct interface_info *));
+ssize_t send_fallback PROTO ((struct interface_info *,
+ struct packet *, struct dhcp_packet *, size_t,
+ struct in_addr,
+ struct sockaddr_in *, struct hardware *));
+void fallback_discard PROTO ((struct protocol *));
+#endif
+
+#ifdef USE_SOCKET_SEND
+void if_reinitialize_send PROTO ((struct interface_info *));
+void if_register_send PROTO ((struct interface_info *));
+ssize_t send_packet PROTO ((struct interface_info *,
+ struct packet *, struct dhcp_packet *, size_t,
+ struct in_addr,
+ struct sockaddr_in *, struct hardware *));
+#endif
+#ifdef USE_SOCKET_RECEIVE
+void if_reinitialize_receive PROTO ((struct interface_info *));
+void if_register_receive PROTO ((struct interface_info *));
+ssize_t receive_packet PROTO ((struct interface_info *,
+ unsigned char *, size_t,
+ struct sockaddr_in *, struct hardware *));
+#endif
+#if defined (USE_SOCKET_SEND) && !defined (USE_SOCKET_FALLBACK)
+void if_enable PROTO ((struct interface_info *));
+#endif
+
+/* bpf.c */
+#if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE)
+int if_register_bpf PROTO ( (struct interface_info *));
+#endif
+#ifdef USE_BPF_SEND
+void if_reinitialize_send PROTO ((struct interface_info *));
+void if_register_send PROTO ((struct interface_info *));
+ssize_t send_packet PROTO ((struct interface_info *,
+ struct packet *, struct dhcp_packet *, size_t,
+ struct in_addr,
+ struct sockaddr_in *, struct hardware *));
+#endif
+#ifdef USE_BPF_RECEIVE
+void if_reinitialize_receive PROTO ((struct interface_info *));
+void if_register_receive PROTO ((struct interface_info *));
+ssize_t receive_packet PROTO ((struct interface_info *,
+ unsigned char *, size_t,
+ struct sockaddr_in *, struct hardware *));
+#endif
+#if defined (USE_BPF_SEND)
+void if_enable PROTO ((struct interface_info *));
+#endif
+
+/* nit.c */
+#if defined (USE_NIT_SEND) || defined (USE_NIT_RECEIVE)
+int if_register_nit PROTO ( (struct interface_info *));
+#endif
+
+#ifdef USE_NIT_SEND
+void if_reinitialize_send PROTO ((struct interface_info *));
+void if_register_send PROTO ((struct interface_info *));
+ssize_t send_packet PROTO ((struct interface_info *,
+ struct packet *, struct dhcp_packet *, size_t,
+ struct in_addr,
+ struct sockaddr_in *, struct hardware *));
+#endif
+#ifdef USE_NIT_RECEIVE
+void if_reinitialize_receive PROTO ((struct interface_info *));
+void if_register_receive PROTO ((struct interface_info *));
+ssize_t receive_packet PROTO ((struct interface_info *,
+ unsigned char *, size_t,
+ struct sockaddr_in *, struct hardware *));
+#endif
+#if defined (USE_BPF_SEND)
+void if_enable PROTO ((struct interface_info *));
+#endif
+
+/* raw.c */
+#ifdef USE_RAW_SEND
+void if_reinitialize_send PROTO ((struct interface_info *));
+void if_register_send PROTO ((struct interface_info *));
+ssize_t send_packet PROTO ((struct interface_info *,
+ struct packet *, struct dhcp_packet *, size_t,
+ struct in_addr,
+ struct sockaddr_in *, struct hardware *));
+#endif
+
+/* dispatch.c */
+extern struct interface_info *interfaces, *dummy_interfaces;
+extern struct protocol *protocols;
+extern int quiet_interface_discovery;
+extern void (*bootp_packet_handler) PROTO ((struct interface_info *,
+ struct dhcp_packet *, int,
+ unsigned int,
+ struct iaddr, struct hardware *));
+extern struct timeout *timeouts;
+void discover_interfaces PROTO ((int));
+void reinitialize_interfaces PROTO ((void));
+void dispatch PROTO ((void));
+int locate_network PROTO ((struct packet *));
+void add_timeout PROTO ((TIME, void (*) PROTO ((void *)), void *));
+#if 0
+void add_fast_timeout PROTO ((UTIME, void (*) PROTO ((void *)), void *));
+#endif
+void cancel_timeout PROTO ((void (*) PROTO ((void *)), void *));
+void add_protocol PROTO ((char *, int,
+ void (*) PROTO ((struct protocol *)), void *));
+
+void remove_protocol PROTO ((struct protocol *));
+
+/* hash.c */
+struct hash_table *new_hash PROTO ((void));
+void add_hash PROTO ((struct hash_table *, unsigned char *,
+ int, unsigned char *));
+void delete_hash_entry PROTO ((struct hash_table *, unsigned char *, int));
+unsigned char *hash_lookup PROTO ((struct hash_table *, unsigned char *, int));
+
+/* tables.c */
+extern struct option dhcp_options [256];
+extern unsigned char dhcp_option_default_priority_list [];
+extern int sizeof_dhcp_option_default_priority_list;
+extern char *hardware_types [256];
+extern struct hash_table universe_hash;
+extern struct universe dhcp_universe;
+void initialize_universes PROTO ((void));
+
+/* convert.c */
+u_int32_t getULong PROTO ((unsigned char *));
+int32_t getLong PROTO ((unsigned char *));
+u_int16_t getUShort PROTO ((unsigned char *));
+int16_t getShort PROTO ((unsigned char *));
+void putULong PROTO ((unsigned char *, u_int32_t));
+void putLong PROTO ((unsigned char *, int32_t));
+void putUShort PROTO ((unsigned char *, unsigned int));
+void putShort PROTO ((unsigned char *, int));
+
+/* inet.c */
+struct iaddr subnet_number PROTO ((struct iaddr, struct iaddr));
+struct iaddr ip_addr PROTO ((struct iaddr, struct iaddr, u_int32_t));
+struct iaddr broadcast_addr PROTO ((struct iaddr, struct iaddr));
+u_int32_t host_addr PROTO ((struct iaddr, struct iaddr));
+int addr_eq PROTO ((struct iaddr, struct iaddr));
+char *piaddr PROTO ((struct iaddr));
+
+/* dhclient.c */
+extern char *path_dhclient_conf;
+extern char *path_dhclient_db;
+extern char *path_dhclient_pid;
+extern int interfaces_requested;
+
+extern struct client_config top_level_config;
+
+void dhcpoffer PROTO ((struct packet *));
+void dhcpack PROTO ((struct packet *));
+void dhcpnak PROTO ((struct packet *));
+
+void send_discover PROTO ((void *));
+void send_request PROTO ((void *));
+void send_release PROTO ((void *));
+void send_decline PROTO ((void *));
+
+void state_reboot PROTO ((void *));
+void state_init PROTO ((void *));
+void state_selecting PROTO ((void *));
+void state_requesting PROTO ((void *));
+void state_bound PROTO ((void *));
+void state_panic PROTO ((void *));
+
+void bind_lease PROTO ((struct interface_info *));
+
+void make_discover PROTO ((struct interface_info *, struct client_lease *));
+void make_request PROTO ((struct interface_info *, struct client_lease *));
+void make_decline PROTO ((struct interface_info *, struct client_lease *));
+void make_release PROTO ((struct interface_info *, struct client_lease *));
+
+void free_client_lease PROTO ((struct client_lease *));
+void rewrite_client_leases PROTO ((void));
+void write_client_lease PROTO ((struct interface_info *,
+ struct client_lease *));
+char *dhcp_option_ev_name PROTO ((struct option *));
+
+void script_init PROTO ((struct interface_info *, char *,
+ struct string_list *));
+void script_write_params PROTO ((struct interface_info *,
+ char *, struct client_lease *));
+int script_go PROTO ((struct interface_info *));
+
+struct client_lease *packet_to_lease PROTO ((struct packet *));
+void go_daemon PROTO ((void));
+void write_client_pid_file PROTO ((void));
+void status_message PROTO ((struct sysconf_header *, void *));
+void client_location_changed PROTO ((void));
+
+/* db.c */
+int write_lease PROTO ((struct lease *));
+int commit_leases PROTO ((void));
+void db_startup PROTO ((void));
+void new_lease_file PROTO ((void));
+
+/* packet.c */
+u_int32_t checksum PROTO ((unsigned char *, int, u_int32_t));
+u_int32_t wrapsum PROTO ((u_int32_t));
+void assemble_hw_header PROTO ((struct interface_info *, unsigned char *,
+ int *, struct hardware *));
+void assemble_udp_ip_header PROTO ((struct interface_info *, unsigned char *,
+ int *, u_int32_t, u_int32_t, unsigned int,
+ unsigned char *, int));
+ssize_t decode_hw_header PROTO ((struct interface_info *, unsigned char *,
+ int, struct hardware *));
+ssize_t decode_udp_ip_header PROTO ((struct interface_info *, unsigned char *,
+ int, struct sockaddr_in *,
+ unsigned char *, int));
+
+/* dhxpxlt.c */
+void convert_statement PROTO ((FILE *));
+void convert_host_statement PROTO ((FILE *, jrefproto));
+void convert_host_name PROTO ((FILE *, jrefproto));
+void convert_class_statement PROTO ((FILE *, jrefproto, int));
+void convert_class_decl PROTO ((FILE *, jrefproto));
+void convert_lease_time PROTO ((FILE *, jrefproto, char *));
+void convert_shared_net_statement PROTO ((FILE *, jrefproto));
+void convert_subnet_statement PROTO ((FILE *, jrefproto));
+void convert_subnet_decl PROTO ((FILE *, jrefproto));
+void convert_host_decl PROTO ((FILE *, jrefproto));
+void convert_hardware_decl PROTO ((FILE *, jrefproto));
+void convert_hardware_addr PROTO ((FILE *, jrefproto));
+void convert_filename_decl PROTO ((FILE *, jrefproto));
+void convert_servername_decl PROTO ((FILE *, jrefproto));
+void convert_ip_addr_or_hostname PROTO ((FILE *, jrefproto, int));
+void convert_fixed_addr_decl PROTO ((FILE *, jrefproto));
+void convert_option_decl PROTO ((FILE *, jrefproto));
+void convert_timestamp PROTO ((FILE *, jrefproto));
+void convert_lease_statement PROTO ((FILE *, jrefproto));
+void convert_address_range PROTO ((FILE *, jrefproto));
+void convert_date PROTO ((FILE *, jrefproto, char *));
+void convert_numeric_aggregate PROTO ((FILE *, jrefproto, int, int, int, int));
+void indent PROTO ((int));
+
+/* route.c */
+void add_route_direct PROTO ((struct interface_info *, struct in_addr));
+void add_route_net PROTO ((struct interface_info *, struct in_addr,
+ struct in_addr));
+void add_route_default_gateway PROTO ((struct interface_info *,
+ struct in_addr));
+void remove_routes PROTO ((struct in_addr));
+void remove_if_route PROTO ((struct interface_info *, struct in_addr));
+void remove_all_if_routes PROTO ((struct interface_info *));
+void set_netmask PROTO ((struct interface_info *, struct in_addr));
+void set_broadcast_addr PROTO ((struct interface_info *, struct in_addr));
+void set_ip_address PROTO ((struct interface_info *, struct in_addr));
+
+/* clparse.c */
+int read_client_conf PROTO ((void));
+void read_client_leases PROTO ((void));
+void parse_client_statement PROTO ((FILE *, struct interface_info *,
+ struct client_config *));
+int parse_X PROTO ((FILE *, u_int8_t *, int));
+int parse_option_list PROTO ((FILE *, u_int8_t *));
+void parse_interface_declaration PROTO ((FILE *, struct client_config *));
+struct interface_info *interface_or_dummy PROTO ((char *));
+void make_client_state PROTO ((struct interface_info *));
+void make_client_config PROTO ((struct interface_info *,
+ struct client_config *));
+void parse_client_lease_statement PROTO ((FILE *, int));
+void parse_client_lease_declaration PROTO ((FILE *, struct client_lease *,
+ struct interface_info **));
+struct option *parse_option_decl PROTO ((FILE *, struct option_data *));
+void parse_string_list PROTO ((FILE *, struct string_list **, int));
+int parse_ip_addr PROTO ((FILE *, struct iaddr *));
+void parse_reject_statement PROTO ((FILE *, struct client_config *));
+
+/* dhcrelay.c */
+void relay PROTO ((struct interface_info *, struct dhcp_packet *, int,
+ unsigned int, struct iaddr, struct hardware *));
+
+/* icmp.c */
+void icmp_startup PROTO ((int, void (*) PROTO ((struct iaddr,
+ u_int8_t *, int))));
+int icmp_echorequest PROTO ((struct iaddr *));
+void icmp_echoreply PROTO ((struct protocol *));
+
+/* dns.c */
+void dns_startup PROTO ((void));
+int ns_inaddr_lookup PROTO ((u_int16_t, struct iaddr));
+void dns_packet PROTO ((struct protocol *));
+
+/* resolv.c */
+extern char path_resolv_conf [];
+struct name_server *name_servers;
+struct domain_search_list *domains;
+
+void read_resolv_conf PROTO ((TIME));
+struct sockaddr_in *pick_name_server PROTO ((void));
+
+/* inet_addr.c */
+#ifdef NEED_INET_ATON
+int inet_aton PROTO ((const char *, struct in_addr *));
+#endif
+
+/* sysconf.c */
+void sysconf_startup PROTO ((void (*) (struct sysconf_header *, void *)));
+void sysconf_restart PROTO ((void *));
+void sysconf_message PROTO ((struct protocol *proto));
diff --git a/contrib/isc-dhcp/includes/dhctoken.h b/contrib/isc-dhcp/includes/dhctoken.h
new file mode 100644
index 000000000000..88acd1622983
--- /dev/null
+++ b/contrib/isc-dhcp/includes/dhctoken.h
@@ -0,0 +1,131 @@
+/* dhctoken.h
+
+ Tokens for config file lexer and parser. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#define SEMI ';'
+#define DOT '.'
+#define COLON ':'
+#define COMMA ','
+#define SLASH '/'
+#define LBRACE '{'
+#define RBRACE '}'
+
+#define FIRST_TOKEN HOST
+#define HOST 256
+#define HARDWARE 257
+#define FILENAME 258
+#define FIXED_ADDR 259
+#define OPTION 260
+#define ETHERNET 261
+#define STRING 262
+#define NUMBER 263
+#define NUMBER_OR_NAME 264
+#define NAME 265
+#define TIMESTAMP 266
+#define STARTS 267
+#define ENDS 268
+#define UID 269
+#define CLASS 270
+#define LEASE 271
+#define RANGE 272
+#define PACKET 273
+#define CIADDR 274
+#define YIADDR 275
+#define SIADDR 276
+#define GIADDR 277
+#define SUBNET 278
+#define NETMASK 279
+#define DEFAULT_LEASE_TIME 280
+#define MAX_LEASE_TIME 281
+#define VENDOR_CLASS 282
+#define USER_CLASS 283
+#define SHARED_NETWORK 284
+#define SERVER_NAME 285
+#define DYNAMIC_BOOTP 286
+#define SERVER_IDENTIFIER 287
+#define DYNAMIC_BOOTP_LEASE_CUTOFF 288
+#define DYNAMIC_BOOTP_LEASE_LENGTH 289
+#define BOOT_UNKNOWN_CLIENTS 290
+#define NEXT_SERVER 291
+#define TOKEN_RING 292
+#define GROUP 293
+#define ONE_LEASE_PER_CLIENT 294
+#define GET_LEASE_HOSTNAMES 295
+#define USE_HOST_DECL_NAMES 296
+#define SEND 297
+#define CLIENT_IDENTIFIER 298
+#define REQUEST 299
+#define REQUIRE 300
+#define TIMEOUT 301
+#define RETRY 302
+#define SELECT_TIMEOUT 303
+#define SCRIPT 304
+#define INTERFACE 305
+#define RENEW 306
+#define REBIND 307
+#define EXPIRE 308
+#define UNKNOWN_CLIENTS 309
+#define ALLOW 310
+#define BOOTP 311
+#define DENY 312
+#define BOOTING 313
+#define DEFAULT 314
+#define MEDIA 315
+#define MEDIUM 316
+#define ALIAS 317
+#define REBOOT 318
+#define ABANDONED 319
+#define BACKOFF_CUTOFF 320
+#define INITIAL_INTERVAL 321
+#define NAMESERVER 322
+#define DOMAIN 323
+#define SEARCH 324
+#define SUPERSEDE 325
+#define APPEND 326
+#define PREPEND 327
+#define HOSTNAME 328
+#define CLIENT_HOSTNAME 329
+#define REJECT 330
+
+#define is_identifier(x) ((x) >= FIRST_TOKEN && \
+ (x) != STRING && \
+ (x) != NUMBER && \
+ (x) != EOF)
diff --git a/contrib/isc-dhcp/includes/hash.h b/contrib/isc-dhcp/includes/hash.h
new file mode 100644
index 000000000000..1bebb3140f80
--- /dev/null
+++ b/contrib/isc-dhcp/includes/hash.h
@@ -0,0 +1,56 @@
+/* hash.h
+
+ Definitions for hashing... */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#define DEFAULT_HASH_SIZE 97
+
+struct hash_bucket {
+ struct hash_bucket *next;
+ unsigned char *name;
+ int len;
+ unsigned char *value;
+};
+
+struct hash_table {
+ int hash_count;
+ struct hash_bucket *buckets [DEFAULT_HASH_SIZE];
+};
+
diff --git a/contrib/isc-dhcp/includes/inet.h b/contrib/isc-dhcp/includes/inet.h
new file mode 100644
index 000000000000..1cedc2331a24
--- /dev/null
+++ b/contrib/isc-dhcp/includes/inet.h
@@ -0,0 +1,52 @@
+/* inet.h
+
+ Portable definitions for internet addresses */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+/* An internet address of up to 128 bits. */
+
+struct iaddr {
+ int len;
+ unsigned char iabuf [16];
+};
+
+struct iaddrlist {
+ struct iaddrlist *next;
+ struct iaddr addr;
+};
diff --git a/contrib/isc-dhcp/includes/netinet/if_ether.h b/contrib/isc-dhcp/includes/netinet/if_ether.h
new file mode 100644
index 000000000000..cae53863c54c
--- /dev/null
+++ b/contrib/isc-dhcp/includes/netinet/if_ether.h
@@ -0,0 +1,74 @@
+/* $NetBSD: if_ether.h,v 1.20 1995/06/12 00:47:27 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)if_ether.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Ethernet address - 6 octets
+ * this is only used by the ethers(3) functions.
+ */
+struct ether_addr {
+ u_int8_t ether_addr_octet[6];
+};
+
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+#define ETHER_ADDR_LEN 6
+
+struct ether_header {
+ u_int8_t ether_dhost[ETHER_ADDR_LEN];
+ u_int8_t ether_shost[ETHER_ADDR_LEN];
+ u_int16_t ether_type;
+};
+
+#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
+#define ETHERTYPE_IP 0x0800 /* IP protocol */
+#define ETHERTYPE_ARP 0x0806 /* address resolution protocol */
+#define ETHERTYPE_REVARP 0x8035 /* reverse addr resolution protocol */
+
+/*
+ * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
+ * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
+ * by an ETHER type (as given above) and then the (variable-length) header.
+ */
+#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
+#define ETHERTYPE_NTRAILER 16
+
+#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
+
+#define ETHERMTU 1500
+#define ETHERMIN (60-14)
+
diff --git a/contrib/isc-dhcp/includes/netinet/ip.h b/contrib/isc-dhcp/includes/netinet/ip.h
new file mode 100644
index 000000000000..233abd6e69b5
--- /dev/null
+++ b/contrib/isc-dhcp/includes/netinet/ip.h
@@ -0,0 +1,171 @@
+/* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ip.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Definitions for internet protocol version 4.
+ * Per RFC 791, September 1981.
+ */
+#define IPVERSION 4
+
+/*
+ * Structure of an internet header, naked of options.
+ *
+ * We declare ip_len and ip_off to be short, rather than u_short
+ * pragmatically since otherwise unsigned comparisons can result
+ * against negative integers quite easily, and fail in subtle ways.
+ */
+struct ip {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_int8_t ip_hl:4, /* header length */
+ ip_v:4; /* version */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int8_t ip_v:4, /* version */
+ ip_hl:4; /* header length */
+#endif
+ u_int8_t ip_tos; /* type of service */
+ int16_t ip_len; /* total length */
+ u_int16_t ip_id; /* identification */
+ int16_t ip_off; /* fragment offset field */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_int8_t ip_ttl; /* time to live */
+ u_int8_t ip_p; /* protocol */
+ u_int16_t ip_sum; /* checksum */
+ struct in_addr ip_src, ip_dst; /* source and dest address */
+};
+
+#define IP_MAXPACKET 65535 /* maximum packet size */
+
+/*
+ * Definitions for IP type of service (ip_tos)
+ */
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+/* IPTOS_LOWCOST 0x02 XXX */
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (hopefully unused)
+ */
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_ROUTINE 0x00
+
+/*
+ * Definitions for options.
+ */
+#define IPOPT_COPIED(o) ((o)&0x80)
+#define IPOPT_CLASS(o) ((o)&0x60)
+#define IPOPT_NUMBER(o) ((o)&0x1f)
+
+#define IPOPT_CONTROL 0x00
+#define IPOPT_RESERVED1 0x20
+#define IPOPT_DEBMEAS 0x40
+#define IPOPT_RESERVED2 0x60
+
+#define IPOPT_EOL 0 /* end of option list */
+#define IPOPT_NOP 1 /* no operation */
+
+#define IPOPT_RR 7 /* record packet route */
+#define IPOPT_TS 68 /* timestamp */
+#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
+#define IPOPT_LSRR 131 /* loose source route */
+#define IPOPT_SATID 136 /* satnet id */
+#define IPOPT_SSRR 137 /* strict source route */
+
+/*
+ * Offsets to fields in options other than EOL and NOP.
+ */
+#define IPOPT_OPTVAL 0 /* option ID */
+#define IPOPT_OLEN 1 /* option length */
+#define IPOPT_OFFSET 2 /* offset within option */
+#define IPOPT_MINOFF 4 /* min value of above */
+
+/*
+ * Time stamp option structure.
+ */
+struct ip_timestamp {
+ u_int8_t ipt_code; /* IPOPT_TS */
+ u_int8_t ipt_len; /* size of structure (variable) */
+ u_int8_t ipt_ptr; /* index of current entry */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_int8_t ipt_flg:4, /* flags, see below */
+ ipt_oflw:4; /* overflow counter */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_int8_t ipt_oflw:4, /* overflow counter */
+ ipt_flg:4; /* flags, see below */
+#endif
+ union ipt_timestamp {
+ u_int32_t ipt_time[1];
+ struct ipt_ta {
+ struct in_addr ipt_addr;
+ u_int32_t ipt_time;
+ } ipt_ta[1];
+ } ipt_timestamp;
+};
+
+/* flag bits for ipt_flg */
+#define IPOPT_TS_TSONLY 0 /* timestamps only */
+#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
+#define IPOPT_TS_PRESPEC 3 /* specified modules only */
+
+/* bits for security (not byte swapped) */
+#define IPOPT_SECUR_UNCLASS 0x0000
+#define IPOPT_SECUR_CONFID 0xf135
+#define IPOPT_SECUR_EFTO 0x789a
+#define IPOPT_SECUR_MMMM 0xbc4d
+#define IPOPT_SECUR_RESTR 0xaf13
+#define IPOPT_SECUR_SECRET 0xd788
+#define IPOPT_SECUR_TOPSECRET 0x6bc5
+
+/*
+ * Internet implementation parameters.
+ */
+#define MAXTTL 255 /* maximum time to live (seconds) */
+#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
+#define IPFRAGTTL 60 /* time to live for frags, slowhz */
+#define IPTTLDEC 1 /* subtracted when forwarding */
+
+#define IP_MSS 576 /* default maximum segment size */
diff --git a/contrib/isc-dhcp/includes/netinet/ip_icmp.h b/contrib/isc-dhcp/includes/netinet/ip_icmp.h
new file mode 100644
index 000000000000..8fffb58b7362
--- /dev/null
+++ b/contrib/isc-dhcp/includes/netinet/ip_icmp.h
@@ -0,0 +1,182 @@
+/* $NetBSD: ip_icmp.h,v 1.11 1996/08/03 15:48:18 neil Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
+ */
+
+
+/*
+ * Interface Control Message Protocol Definitions.
+ * Per RFC 792, September 1981.
+ */
+
+/*
+ * Internal of an ICMP Router Advertisement
+ */
+struct icmp_ra_addr {
+ u_int32_t ira_addr;
+ u_int32_t ira_preference;
+};
+
+/*
+ * Structure of an icmp header.
+ */
+struct icmp {
+ u_int8_t icmp_type; /* type of message, see below */
+ u_int8_t icmp_code; /* type sub code */
+ u_int16_t icmp_cksum; /* ones complement cksum of struct */
+ union {
+ u_int8_t ih_pptr; /* ICMP_PARAMPROB */
+ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
+ struct ih_idseq {
+ int16_t icd_id;
+ int16_t icd_seq;
+ } ih_idseq;
+ int32_t ih_void;
+
+ /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
+ struct ih_pmtu {
+ int16_t ipm_void;
+ int16_t ipm_nextmtu;
+ } ih_pmtu;
+ struct ih_rtradv {
+ u_int8_t irt_num_addrs;
+ u_int8_t irt_wpa;
+ u_int16_t irt_lifetime;
+ } ih_rtradv;
+ } icmp_hun;
+#define icmp_pptr icmp_hun.ih_pptr
+#define icmp_gwaddr icmp_hun.ih_gwaddr
+#define icmp_id icmp_hun.ih_idseq.icd_id
+#define icmp_seq icmp_hun.ih_idseq.icd_seq
+#define icmp_void icmp_hun.ih_void
+#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
+#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
+#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
+#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
+#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
+ union {
+ struct id_ts {
+ u_int32_t its_otime;
+ u_int32_t its_rtime;
+ u_int32_t its_ttime;
+ } id_ts;
+ struct id_ip {
+ struct ip idi_ip;
+ /* options and then 64 bits of data */
+ } id_ip;
+ struct icmp_ra_addr id_radv;
+ u_int32_t id_mask;
+ int8_t id_data[1];
+ } icmp_dun;
+#define icmp_otime icmp_dun.id_ts.its_otime
+#define icmp_rtime icmp_dun.id_ts.its_rtime
+#define icmp_ttime icmp_dun.id_ts.its_ttime
+#define icmp_ip icmp_dun.id_ip.idi_ip
+#define icmp_radv icmp_dun.id_mask
+#define icmp_mask icmp_dun.id_mask
+#define icmp_data icmp_dun.id_data
+};
+
+/*
+ * Lower bounds on packet lengths for various types.
+ * For the error advice packets must first insure that the
+ * packet is large enought to contain the returned ip header.
+ * Only then can we do the check to see if 64 bits of packet
+ * data have been returned, since we need to check the returned
+ * ip header length.
+ */
+#define ICMP_MINLEN 8 /* abs minimum */
+#define ICMP_TSLEN (8 + 3 * sizeof (u_int32_t)) /* timestamp */
+#define ICMP_MASKLEN 12 /* address mask */
+#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
+#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
+ /* N.B.: must separately check that ip_hl >= 5 */
+
+/*
+ * Definition of type and code field values.
+ */
+#define ICMP_ECHOREPLY 0 /* echo reply */
+#define ICMP_UNREACH 3 /* dest unreachable, codes: */
+#define ICMP_UNREACH_NET 0 /* bad net */
+#define ICMP_UNREACH_HOST 1 /* bad host */
+#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
+#define ICMP_UNREACH_PORT 3 /* bad port */
+#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
+#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
+#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
+#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
+#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
+#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
+#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
+#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
+#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
+#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
+#define ICMP_REDIRECT 5 /* shorter route, codes: */
+#define ICMP_REDIRECT_NET 0 /* for network */
+#define ICMP_REDIRECT_HOST 1 /* for host */
+#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
+#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
+#define ICMP_ECHO 8 /* echo service */
+#define ICMP_ROUTERADVERT 9 /* router advertisement */
+#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
+#define ICMP_TIMXCEED 11 /* time exceeded, code: */
+#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
+#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
+#define ICMP_PARAMPROB 12 /* ip header bad */
+#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
+#define ICMP_TSTAMP 13 /* timestamp request */
+#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
+#define ICMP_IREQ 15 /* information request */
+#define ICMP_IREQREPLY 16 /* information reply */
+#define ICMP_MASKREQ 17 /* address mask request */
+#define ICMP_MASKREPLY 18 /* address mask reply */
+
+#define ICMP_MAXTYPE 18
+
+#define ICMP_INFOTYPE(type) \
+ ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
+ (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
+ (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
+ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
+ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
+
+#ifdef _KERNEL
+void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *));
+void icmp_input __P((struct mbuf *, ...));
+void icmp_reflect __P((struct mbuf *));
+void icmp_send __P((struct mbuf *, struct mbuf *));
+int icmp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
+#endif
+
diff --git a/contrib/isc-dhcp/includes/netinet/udp.h b/contrib/isc-dhcp/includes/netinet/udp.h
new file mode 100644
index 000000000000..c7964dfd30fc
--- /dev/null
+++ b/contrib/isc-dhcp/includes/netinet/udp.h
@@ -0,0 +1,47 @@
+/* $NetBSD: udp.h,v 1.6 1995/04/13 06:37:10 cgd Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)udp.h 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Udp protocol header.
+ * Per RFC 768, September, 1981.
+ */
+struct udphdr {
+ u_int16_t uh_sport; /* source port */
+ u_int16_t uh_dport; /* destination port */
+ int16_t uh_ulen; /* udp length */
+ u_int16_t uh_sum; /* udp checksum */
+};
diff --git a/contrib/isc-dhcp/includes/osdep.h b/contrib/isc-dhcp/includes/osdep.h
new file mode 100644
index 000000000000..4ea4cd863d75
--- /dev/null
+++ b/contrib/isc-dhcp/includes/osdep.h
@@ -0,0 +1,220 @@
+/* osdep.h
+
+ Operating system dependencies... */
+
+/*
+ * Copyright (c) 1996, 1997, 1998 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE INTERNET SOFTWARE CONSORTIUM OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software was written for the Internet Software Consortium by Ted Lemon
+ * under a contract with Vixie Laboratories.
+ */
+
+#include "site.h"
+
+/* Porting::
+
+ If you add a new network API, you must add a check for it below: */
+
+#if !defined (USE_SOCKETS) && \
+ !defined (USE_SOCKET_SEND) && \
+ !defined (USE_SOCKET_RECEIVE) && \
+ !defined (USE_RAW_SOCKETS) && \
+ !defined (USE_RAW_SEND) && \
+ !defined (USE_SOCKET_RECEIVE) && \
+ !defined (USE_BPF) && \
+ !defined (USE_BPF_SEND) && \
+ !defined (USE_BPF_RECEIVE) && \
+ !defined (USE_NIT) && \
+ !defined (USE_NIT_SEND) && \
+ !defined (USE_NIT_RECEIVE) && \
+ !defined (USR_DLPI_SEND) && \
+ !defined (USE_DLPI_RECEIVE)
+# define USE_DEFAULT_NETWORK
+#endif
+
+
+/* Porting::
+
+ If you add a new system configuration file, include it here: */
+
+#if defined (sun)
+# if defined (__svr4__) || defined (__SVR4)
+# include "cf/sunos5-5.h"
+# else
+# include "cf/sunos4.h"
+# endif
+#endif
+
+#ifdef bsdi
+# include "cf/bsdos.h"
+#endif
+
+#ifdef __NetBSD__
+# include "cf/netbsd.h"
+#endif
+
+#ifdef __FreeBSD__
+# include "cf/freebsd.h"
+#endif
+
+#if defined (__osf__) && defined (__alpha)
+# include "cf/alphaosf.h"
+#endif
+
+#ifdef ultrix
+# include "cf/ultrix.h"
+#endif
+
+#ifdef linux
+# include "cf/linux.h"
+#endif
+
+#ifdef SCO
+# include "cf/sco.h"
+#endif
+
+#ifdef hpux
+# include "cf/hpux.h"
+#endif
+
+#ifdef __QNX__
+# include "cf/qnx.h"
+#endif
+
+#ifdef __CYGWIN32__
+# include "cf/cygwin32.h"
+#endif
+
+#ifdef NeXT
+# ifdef __APPLE__
+# include "cf/rhapsody.h"
+# else
+# include "cf/nextstep.h"
+# endif
+#endif
+
+/* Porting::
+
+ If you add a new network API, and have it set up so that it can be
+ used for sending or receiving, but doesn't have to be used for both,
+ then set up an ifdef like the ones below: */
+
+#ifdef USE_SOCKETS
+# define USE_SOCKET_SEND
+# define USE_SOCKET_RECEIVE
+#endif
+
+#ifdef USE_RAW_SOCKETS
+# define USE_RAW_SEND
+# define USE_SOCKET_RECEIVE
+#endif
+
+#ifdef USE_BPF
+# define USE_BPF_SEND
+# define USE_BPF_RECEIVE
+#endif
+
+#ifdef USE_NIT
+# define USE_NIT_SEND
+# define USE_NIT_RECEIVE
+#endif
+
+#ifdef USE_DLPI
+# define USE_DLPI_SEND
+# define USE_DLPI_RECEIVE
+#endif
+
+#ifdef USE_UPF
+# define USE_UPF_SEND
+# define USE_UPF_RECEIVE
+#endif
+
+/* Porting::
+
+ If you add support for sending packets directly out an interface,
+ and your support does not do ARP or routing, you must use a fallback
+ mechanism to deal with packets that need to be sent to routers.
+ Currently, all low-level packet interfaces use BSD sockets as a
+ fallback. */
+
+#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \
+ defined (USE_DLPI_SEND) || defined (USE_UPF_SEND)
+# define USE_SOCKET_FALLBACK
+# define USE_FALLBACK
+#endif
+
+/* Porting::
+
+ If you add support for sending packets directly out an interface
+ and need to be able to assemble packets, add the USE_XXX_SEND
+ definition for your interface to the list tested below. */
+
+#if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \
+ defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \
+ defined (USE_DLPI_SEND)
+# define PACKET_ASSEMBLY
+#endif
+
+/* Porting::
+
+ If you add support for receiving packets directly from an interface
+ and need to be able to decode raw packets, add the USE_XXX_RECEIVE
+ definition for your interface to the list tested below. */
+
+#if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \
+ defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \
+ defined (USE_DLPI_RECEIVE)
+# define PACKET_DECODING
+#endif
+
+/* If we don't have a DLPI packet filter, we have to filter in userland.
+ Probably not worth doing, actually. */
+#if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD)
+# define USERLAND_FILTER
+#endif
+
+/* jmp_buf is assumed to be a struct unless otherwise defined in the
+ system header. */
+#ifndef jbp_decl
+# define jbp_decl(x) jmp_buf *x
+#endif
+#ifndef jref
+# define jref(x) (&(x))
+#endif
+#ifndef jdref
+# define jdref(x) (*(x))
+#endif
+#ifndef jrefproto
+# define jrefproto jmp_buf *
+#endif
+
+#ifndef BPF_FORMAT
+# define BPF_FORMAT "/dev/bpf%d"
+#endif
diff --git a/contrib/isc-dhcp/includes/site.h b/contrib/isc-dhcp/includes/site.h
new file mode 100644
index 000000000000..30fdb7030050
--- /dev/null
+++ b/contrib/isc-dhcp/includes/site.h
@@ -0,0 +1,100 @@
+/* Site-specific definitions.
+
+ For supported systems, you shouldn't need to make any changes here.
+ However, you may want to, in order to deal with site-specific
+ differences. */
+
+/* Add any site-specific definitions and inclusions here... */
+
+/* #include <site-foo-bar.h> */
+/* #define SITE_FOOBAR */
+
+/* Define this if you don't want dhcpd to run as a daemon and do want
+ to see all its output printed to stdout instead of being logged via
+ syslog(). This also makes dhcpd use the dhcpd.conf in its working
+ directory and write the dhcpd.leases file there. */
+
+/* #define DEBUG */
+
+/* Define this to see what the parser is parsing. You probably don't
+ want to see this. */
+
+/* #define DEBUG_TOKENS */
+
+/* Define this to see dumps of incoming and outgoing packets. This
+ slows things down quite a bit... */
+
+/* #define DEBUG_PACKET */
+
+/* Define this if you want to see dumps of tree evaluations. The most
+ common reason for doing this is to watch what happens with DNS name
+ lookups. */
+
+/* #define DEBUG_EVAL */
+
+/* Define this if you want the dhcpd.pid file to go somewhere other than
+ the default (which varies from system to system, but is usually either
+ /etc or /var/run. */
+
+/* #define _PATH_DHCPD_PID "/var/run/dhcpd.pid" */
+
+/* Define this if you want the dhcpd.leases file (the dynamic lease database)
+ to go somewhere other than the default location, which is normally
+ /etc/dhcpd.leases. */
+
+/* #define _PATH_DHCPD_DB "/etc/dhcpd.leases" */
+
+/* Define this if you want the dhcpd.conf file to go somewhere other than
+ the default location. By default, it goes in /etc/dhcpd.conf. */
+
+/* #define _PATH_DHCPD_CONF "/etc/dhcpd.conf" */
+
+/* Network API definitions. You do not need to choose one of these - if
+ you don't choose, one will be chosen for you in your system's config
+ header. DON'T MESS WITH THIS UNLESS YOU KNOW WHAT YOU'RE DOING!!! */
+
+/* Define this to use the standard BSD socket API.
+
+ On many systems, the BSD socket API does not provide the ability to
+ send packets to the 255.255.255.255 broadcast address, which can
+ prevent some clients (e.g., Win95) from seeing replies. This is
+ not a problem on Solaris.
+
+ In addition, the BSD socket API will not work when more than one
+ network interface is configured on the server.
+
+ However, the BSD socket API is about as efficient as you can get, so if
+ the aforementioned problems do not matter to you, or if no other
+ API is supported for your system, you may want to go with it. */
+
+/* #define USE_SOCKETS */
+
+/* Define this to use the Sun Streams NIT API.
+
+ The Sun Streams NIT API is only supported on SunOS 4.x releases. */
+
+/* #define USE_NIT */
+
+/* Define this to use the Berkeley Packet Filter API.
+
+ The BPF API is available on all 4.4-BSD derivatives, including
+ NetBSD, FreeBSD and BSDI's BSD/OS. It's also available on
+ DEC Alpha OSF/1 in a compatibility mode supported by the Alpha OSF/1
+ packetfilter interface. */
+
+/* #define USE_BPF */
+
+/* Define this to use the raw socket API.
+
+ The raw socket API is provided on many BSD derivatives, and provides
+ a way to send out raw IP packets. It is only supported for sending
+ packets - packets must be received with the regular socket API.
+ This code is experimental - I've never gotten it to actually transmit
+ a packet to the 255.255.255.255 broadcast address - so use it at your
+ own risk. */
+
+/* #define USE_RAW_SOCKETS */
+
+/* Define this to change the logging facility used by dhcpd. */
+
+/* #define DHCPD_LOG_FACILITY LOG_DAEMON */
diff --git a/contrib/isc-dhcp/includes/sysconf.h b/contrib/isc-dhcp/includes/sysconf.h
new file mode 100644
index 000000000000..5feb4c75c706
--- /dev/null
+++ b/contrib/isc-dhcp/includes/sysconf.h
@@ -0,0 +1,52 @@
+/* systat.h
+
+ Definitions for systat protocol... */
+
+/*
+ * Copyright (c) 1997 The Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#define SYSCONF_SOCKET "/var/run/sysconf"
+
+struct sysconf_header {
+ u_int32_t type; /* Type of status message... */
+ u_int32_t length; /* Length of message. */
+};
+
+/* Message types... */
+#define NETWORK_LOCATION_CHANGED 1
+
diff --git a/contrib/isc-dhcp/includes/tree.h b/contrib/isc-dhcp/includes/tree.h
new file mode 100644
index 000000000000..c2df41f52b11
--- /dev/null
+++ b/contrib/isc-dhcp/includes/tree.h
@@ -0,0 +1,107 @@
+/* tree.h
+
+ Definitions for address trees... */
+
+/*
+ * Copyright (c) 1995 The Internet Software Consortium. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+/* A pair of pointers, suitable for making a linked list. */
+typedef struct _pair {
+ caddr_t car;
+ struct _pair *cdr;
+} *pair;
+
+/* Tree node types... */
+#define TREE_CONCAT 1
+#define TREE_HOST_LOOKUP 2
+#define TREE_CONST 3
+#define TREE_LIMIT 4
+
+/* Tree structure for deferred evaluation of changing values. */
+struct tree {
+ int op;
+ union {
+ struct concat {
+ struct tree *left;
+ struct tree *right;
+ } concat;
+ struct host_lookup {
+ struct dns_host_entry *host;
+ } host_lookup;
+ struct const_val {
+ unsigned char *data;
+ int len;
+ } const_val;
+ struct limit {
+ struct tree *tree;
+ int limit;
+ } limit;
+ } data;
+};
+
+/* DNS host entry structure... */
+struct dns_host_entry {
+ char *hostname;
+ unsigned char *data;
+ int data_len;
+ int buf_len;
+ TIME timeout;
+};
+
+struct tree_cache {
+ unsigned char *value;
+ int len;
+ int buf_size;
+ TIME timeout;
+ struct tree *tree;
+ int flags;
+#define TC_AWAITING_RESOLUTION 1
+#define TC_TEMPORARY 2
+};
+
+struct universe {
+ char *name;
+ struct hash_table *hash;
+ struct option *options [256];
+};
+
+struct option {
+ char *name;
+ char *format;
+ struct universe *universe;
+ unsigned char code;
+};