]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Merge changes between 3.0.3RC1 and 3.0.4-BETA-3 into HEAD (silence
authorDavid Hankins <dhankins@isc.org>
Fri, 24 Feb 2006 23:16:32 +0000 (23:16 +0000)
committerDavid Hankins <dhankins@isc.org>
Fri, 24 Feb 2006 23:16:32 +0000 (23:16 +0000)
  robie).

48 files changed:
LICENSE
README
RELNOTES
client/clparse.c
client/dhclient-script.8
client/dhclient.8
client/dhclient.c
common/alloc.c
common/comapi.c
common/conflex.c
common/discover.c
common/dispatch.c
common/dns.c
common/execute.c
common/options.c
common/parse.c
common/print.c
common/resolv.c
common/tables.c
common/tr.c
common/tree.c
dhcpctl/omshell.c
includes/cf/linux.h
includes/cf/sunos5-5.h
includes/dhcp.h
includes/dhcpd.h
includes/dhctoken.h
includes/omapip/trace.h
includes/osdep.h
omapip/alloc.c
omapip/array.c
omapip/buffer.c
omapip/generic.c
omapip/handle.c
omapip/hash.c
omapip/protocol.c
omapip/support.c
omapip/trace.c
relay/dhcrelay.c
server/confpars.c
server/db.c
server/dhcp.c
server/dhcpd.8
server/dhcpd.conf.5
server/failover.c
server/mdb.c
server/omapi.c
server/salloc.c

diff --git a/LICENSE b/LICENSE
index b737de682df6ee1187e17972e812148de09190db..c912b6396db1ea8e6299a34445aaf07748b9006e 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-# Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+# Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
 # Copyright (c) 1995-2003 by Internet Software Consortium
 #
 # Permission to use, copy, modify, and distribute this software for any
diff --git a/README b/README
index 6f8fd1788c3c25e9aaf71313832bf7f9c5b95d4e..96f886c7ff9218eb33c0076f198d51b1d98d5aff 100644 (file)
--- a/README
+++ b/README
@@ -367,6 +367,18 @@ Linux 2.1 and later kernels do not use SO_BINDTODEVICE or require the
 broadcast address hack, but do support multiple interfaces, using the
 Linux Packet Filter.
 
+                   LINUX: 802.1q VLAN INTERFACES
+
+If you're using 802.1q vlan interfaces on Linux, it is necessary to
+vconfig the subinterface(s) to rewrite the 802.1q information out of
+packets received by the dhcpd daemon via LPF:
+
+       vconfig set_flag eth1.523 1 1
+
+Note that this may affect the performance of your system, since the
+Linux kernel must rewrite packets received via this interface.  For
+more information, consult the vconfig man pages.
+
                                 SCO
 
 SCO has the same problem as Linux (described earlier).  The thing is,
@@ -446,18 +458,24 @@ systems, although it may occur with other systems as well.  If you
 encounter this symptom, and you are running the DHCP server on a
 machine with a single broadcast network interface, you may wish to
 edit the includes/site.h file and uncomment the #define USE_SOCKETS
-line.  Then type ``make clean; make''.
+line.  Then type ``make clean; make''.  As an alternative workaround,
+it has been reported that running 'snoop' will cause the dhcp server
+to start receiving packets.  So the practice reported to us is to run
+snoop at dhcpd startup time, with arguments to cause it to receive one
+packet and exit.
+
+       snoop -c 1 udp port 67 > /dev/null &
 
 The DHCP client on Solaris will only work with DLPI.  If you run it
 and it just keeps saying it's sending DHCPREQUEST packets, but never
 gets a response, you may be having DLPI trouble as described above.
-If so, we have no solution to offer at this time.  Also, because
-Solaris requires you to "plumb" an interface before it can be detected
-by the DHCP client, you must either specify the name(s) of the
-interface(s) you want to configure on the command line, or must plumb
-the interfaces prior to invoking the DHCP client.  This can be done
-with ``ifconfig iface plumb'', where iface is the name of the
-interface (e.g., ``ifconfig hme0 plumb'').
+If so, we have no solution to offer at this time, aside from the above
+workaround which should also work here.  Also, because Solaris requires
+you to "plumb" an interface before it can be detected by the DHCP client,
+you must either specify the name(s) of the interface(s) you want to
+configure on the command line, or must plumb the interfaces prior to
+invoking the DHCP client.  This can be done with ``ifconfig iface plumb'',
+where iface is the name of the interface (e.g., ``ifconfig hme0 plumb'').
 
 It should be noted that Solaris versions from 2.6 onward include a
 DHCP client that you can run with ``/sbin/ifconfig iface dhcp start''
index 38aac4d854e1ec8a6e6346259921af14c9019cb9..692af08e879ee54d09a10ebec56f0c487ccb7c56 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -63,6 +63,144 @@ and for prodding me into improving it.
 - RFC3942 compliance, site-local option spaces start at 224 now, not 128.
         ||| THIS NEEDS TO BE SPELLED OUT IN THE NEW FEATURES LIST |||
 
+
+                       Changes since 3.0.4b2
+
+- Null-termination sensing for certain clients that unfortunatley require
+  it in DHCPINFORM processing was repaired.
+
+- The host-name option and a few others were moved from "X" format to "t"
+  format to be compatible with new NULL handling functions.
+
+- DHCPINFORM processing is a little more careful about return addressing
+  its responses, or if responding via a relay.  The INFORM related
+  messages also log the 'effective client ip address' rather than the
+  client's supplied ciaddr (since some clients produce null ciaddrs).
+
+- The server was inappropriately sending leases to the RESET state in the
+  event that multiple active leases were found to match a singly-identified
+  client.  This was changed to RELEASED (by accepting a different, ACTIVE
+  binding, the client is implicitly releasing its lease).  This repairs a
+  bug wherein secondary servers in failover pairs detecting this condition
+  move leases to RESET, and primaries refuse to accept that state
+  transition (properly).
+
+- The memset-after-dmalloc() changes made in 3.0.4b1 have been backed out.
+
+                       Changes since 3.0.4b1
+
+- Command line parsing in omshell was repaired - it no longer closes
+  STDIN after reading one line.
+
+- The resolver library no longer closes the /etc/resolv.conf file
+  descriptor it opened twice.
+
+- Changes to trailing NULL removal in 't' option-atoms has been rethought,
+  it now includes 'd' (domain name) types, and tries hard not to rewind an
+  option beyond the start of the text field it is un-terminating.
+
+                       Changes since 3.0.3
+
+- A DDNS update handling function was misusing the DNS error codes, rather
+  than the internal generic result enumeration.  The result is a confusing
+  syslog line, logging the wrong condition.
+
+- The DHCP Server was not checking pool balance in the case where it brought
+  a non-ACTIVE lease out of storage for a client that was returning to use
+  a lease it once had long ago, and had since expired.
+
+- Failover peers no longer bother to look for free leases to allocate when
+  they already found the client's ACTIVE lease.  DISCOVERs are load balanced
+  wether freely-allocated or not, unless the server doubts the peer has
+  leases to allocate.
+
+- Fixed a bug in dhcrelay agent addition code that suppressed trailing
+  PAD options - it was suppressing only one trailng PAD option, rather
+  than the entire block of them.
+
+- Fixed some unlikely overlapping-region memcpy() bugs in dhcrelay agent
+  option addition and stripping code.  Added a few sanity checks.
+
+- Added some sanity checks to OMAPI connection/authentication code.
+
+- dmalloc() memset()'s the non-debug (data) portion of the allocated
+  memory to zero.  Code that memset()'s the result returned by dmalloc() to
+  zero is redundant.  These redundancies were removed.
+
+- Some type declaration corrections to u_int16_t were made in common/tr.c
+  (Token Ring support) thanks to a patch from Jason Vas Dias at RedHat.
+
+- A failover bug that was allowing leases that EXPIRED or were RELEASED
+  where tsfp and tstp are identical timestamps to languish in these
+  transitional states has been repaired.  As a side effect, lease
+  databases should be kept more consistent overall, not just for these
+  transitional states.
+
+- If the lease db is deleted out from under the daemon, and it moves to rewrite
+  the db, it will go ahead with the operation and move the new db into place
+  once it detects the old db does not exist.
+
+- dhclient now ignores IRDA, SIT, and IEEE1394 network interfaces, as it
+  is either nonsensical or (in the case of IEEE1394) is not known to support
+  these interfaces.  Thanks to Marius Gedminas and Andrew Pollock of Debian.
+
+- Some previously undocumented reasons for dhclient-script invoking has
+  been doucmented in the dhclient-script.8 manpage.
+
+- Failover potential expiry calculations (TSTP) have been corrected.  Results
+  should be substantially more consistent, and proper given the constraints.
+
+- Adjusted lease state validation checks in potential-conflict, to
+  account for possible clock skew similarly to normal state, and several
+  previously illegal transitions were made legal (ex: active->released).
+
+- An impossible sanity check was removed from omapi/buffer.c, thanks to a
+  patch from 'infamous42md'.
+
+- An OMAPI host/network byte order problem in lease time values has been
+  repaired.
+
+- Several minor bugs, largely relating to treating 8-byte time values as
+  4-byte entities, have been repaired after careful review of the FreeBSD
+  ports collection's patch set.  Thanks to the nameless entities who have
+  contributed to the FreeBSD ports.
+
+- When writing a trace file, the file is now created with permissions 0600,
+  to help administrators avoid accidentally publicising sensitive config
+  data.
+
+- The calculation of the maximum size of DHCP packets no longer includes
+  Ethernet framing overhead.  The result is that the 'Maximum Message
+  Size' option advertised by clients, or the default value 576, is no
+  longer reduced by 14 bytes, and instead directly reflects the IP level
+  MTU (and the default, minimum allowed IP MTU of 576).
+
+- The special status of RELEASED/EXPIRED/RESET leases when a server
+  is operating in partner-down was fixed.  It no longer requires a
+  lease be twice the MCLT beyond STOS to 'reallocate', and the expiry
+  event to turn these into FREE leases without peer acknowledgement
+  (after STOS+MCLT) has been repaired.
+
+- Compilation on older Solaris systems (lacking /usr/include/sys/int_types.h)
+  has been repaired.
+
+- "append"ing a string onto the end of a "t" type option (such as the
+  domain-name field) that had been improperly NULL-terminated by the
+  DHCP server will no longer result in a truncated string containing
+  only the option from the server, and not the expected appended value.
+  Thanks to a patch from Jason Vas Dias at RedHat.
+
+- File handlers on configuration state (config files and lease dbs) should
+  be treated consistently, regardless of wether TRACING is defined or not.
+
+- The linux build environment has had some minor improvements - better
+  sensing of 64-bit pointer sizes (only used for establishing an icmp_id),
+  and corrections to #if operators regarding LINUX_MAJOR should it ever
+  move to 3.[01].x.
+
+- The server now tries harder to survive the condition where it is unable
+  to open a new lease file to rewrite the lease state database.
+
                        Changes since 3.0.3b3
 
 - dhclient.conf documentation for interface {} was updated to reflect recent
index 32d82d025b8179a708927ec47015ea9918492974..dbd54ebed1b4751a84cea61a2056dde4c61eea5b 100644 (file)
@@ -3,7 +3,7 @@
    Parser for dhclient config and lease files... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: clparse.c,v 1.64 2005/03/17 20:14:55 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: clparse.c,v 1.65 2006/02/24 23:16:27 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -173,7 +173,6 @@ int read_client_conf_file (const char *name, struct interface_info *ip,
        status = (cfile -> warnings_occurred
                  ? ISC_R_BADPARSE
                  : ISC_R_SUCCESS);
-       close (file);
        end_parse (&cfile);
        return status;
 }
@@ -210,7 +209,6 @@ void read_client_leases ()
 
        } while (1);
 
-       close (file);
        end_parse (&cfile);
 }
 
@@ -774,7 +772,13 @@ int interface_or_dummy (struct interface_info **pi, const char *name)
                if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
                        log_fatal ("Can't record interface %s: %s",
                                   name, isc_result_totext (status));
-               strcpy (ip -> name, name);
+
+               if (strlen(name) >= sizeof(ip->name)) {
+                       interface_dereference(&ip, MDL);
+                       return 0;
+               }
+               strcpy(ip->name, name);
+
                if (dummy_interfaces) {
                        interface_reference (&ip -> next,
                                             dummy_interfaces, MDL);
@@ -994,7 +998,8 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
                        skip_to_semi (cfile);
                        break;
                }
-               interface_or_dummy (ipp, val);
+               if (!interface_or_dummy (ipp, val))
+                       log_fatal ("Can't allocate interface %s.", val);
                break;
 
              case NAME:
index 078dfe3cdb433abf90c15cba338910e338c47421..214bff79038a4d62d60bb3b39a1b3061e6ab14e6 100644 (file)
@@ -1,6 +1,6 @@
 .\"    dhclient-script.8
 .\"
-.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
@@ -28,7 +28,7 @@
 .\" see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 .\" ``http://www.nominum.com''.
 .\"
-.\" $Id: dhclient-script.8,v 1.10 2005/03/17 20:14:55 dhankins Exp $
+.\" $Id: dhclient-script.8,v 1.11 2006/02/24 23:16:27 dhankins Exp $
 .\"
 .TH dhclient-script 8
 .SH NAME
@@ -97,7 +97,8 @@ defines a set of variables in the environment, and then invokes
 .B CLIENTBINDIR/dhclient-script.
 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, BOUND, RENEW, REBIND, REBOOT, EXPIRE, FAIL and TIMEOUT.
+MEDIUM, PREINIT, BOUND, RENEW, REBIND, REBOOT, EXPIRE, FAIL, STOP, RELEASE,
+NBI and TIMEOUT.
 .PP
 .SH MEDIUM
 The DHCP client is requesting that an interface's media type
@@ -175,6 +176,18 @@ 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 STOP
+The dhclient has been informed to shut down gracefully, the
+dhclient-script should unconfigure or shutdown the interface as
+appropriate.
+.SH RELEASE
+The dhclient has been executed using the -r flag, indicating that the
+administrator wishes it to release its lease(s).  dhclient-script should
+unconfigure or shutdown the interface.
+.SH NBI
+No-Broadcast-Interfaces...dhclient was unable to find any interfaces
+upon which it believed it should commence DHCP.  What dhclient-script
+should do in this situation is entirely up to the implementor.
 .SH TIMEOUT
 The DHCP client has been unable to contact any DHCP servers.
 However, an old lease has been identified, and its parameters have
index 9c00737cf2a5a353ba282bb97bec548565930108..65f56c0c6228470a358bf89e4a6540e87bf156d4 100644 (file)
@@ -24,7 +24,7 @@
 .\" Support and other services are available for ISC products - see
 .\" http://www.isc.org for more information.
 .\"
-.\" $Id: dhclient.8,v 1.17 2005/03/17 20:14:55 dhankins Exp $
+.\" $Id: dhclient.8,v 1.18 2006/02/24 23:16:27 dhankins Exp $
 .\"
 .TH dhclient 8
 .SH NAME
@@ -39,6 +39,10 @@ dhclient - Dynamic Host Configuration Protocol Client
 .B -d
 ]
 [
+.B -e
+.I VAR=value
+]
+[
 .B -q
 ]
 [
@@ -188,6 +192,15 @@ flag should be specified.  This is useful when running the client
 under a debugger, or when running it out of inittab on System V
 systems.
 .PP
+The dhclient daemon creates its own environment when executing the
+dhclient-script to do the grunt work of interface configuration.
+To define extra environment variables and their values, use the
+.B -e
+flag, followed by the environment variable name and value assignment,
+just as one would assign a variable in a shell.  Eg:
+.B -e
+.I IF_METRIC=1
+.PP
 The client normally prints a startup message and displays the
 protocol sequence to the standard error descriptor until it has
 acquired an address, and then only logs messages using the
@@ -238,7 +251,7 @@ broadcast interface may be added after system startup.   The
 .B -w
 flag can be used to cause the client not to exit when it doesn't find
 any such interfaces.   The
-.B omshell (8)
+.B omshell (1)
 program can then be used to notify the client when a network interface
 has been added or removed, so that the client can attempt to configure an IP
 address on that interface.
index 3f31650ef1f5dca413ce3b6c328deb7120e580d5..762d6d76c5d6995efe0755c34f6cbf8a34b8204b 100644 (file)
@@ -3,7 +3,7 @@
    DHCP Client. */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -32,7 +32,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.132 2005/03/17 20:14:55 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.133 2006/02/24 23:16:27 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -212,10 +212,10 @@ int main (argc, argv, envp)
                    if (status != ISC_R_SUCCESS)
                        log_fatal ("Can't record interface %s:%s",
                                   argv [i], isc_result_totext (status));
-                   if (strlen (argv [i]) > sizeof tmp -> name)
-                           log_fatal ("%s: interface name too long (max %ld)",
-                                      argv [i], (long)strlen (argv [i]));
-                   strcpy (tmp -> name, argv [i]);
+                   if (strlen(argv[i]) >= sizeof(tmp->name))
+                           log_fatal("%s: interface name too long (is %ld)",
+                                      argv [i], (long)strlen(argv[i]));
+                   strcpy(tmp->name, argv[i]);
                    if (interfaces) {
                            interface_reference (&tmp -> next,
                                                 interfaces, MDL);
@@ -789,11 +789,9 @@ void dhcpack (packet)
                client -> new -> renewal = TIME_MAX;
 
        /* Now introduce some randomness to the renewal time: */
-       if (client -> new -> renewal <= TIME_MAX / 3 - 3)
-               client -> new -> renewal =
-                               (((client -> new -> renewal + 3) * 3 / 4) +
-                                   (random () % /* XXX NUMS */
-                                    ((client -> new -> renewal + 3) / 4)));
+       if (client->new->renewal <= ((TIME_MAX / 3) - 3))
+               client->new->renewal = (((client->new->renewal * 3) + 3) / 4) +
+                               (((random() % client->new->renewal) + 3) / 4);
 
        /* Same deal with the rebind time. */
        oc = lookup_option (&dhcp_universe, client -> new -> options,
@@ -1404,22 +1402,17 @@ void send_discover (cpp)
           between zero and two times itself.  On average, this means
           that it will double with every transmission. */
        if (increase) {
-               if (!client -> interval)
-                       client -> interval =
-                               client -> config -> initial_interval;
+               if (!client->interval)
+                       client->interval = client->config->initial_interval;
                else
-                       client -> interval += ((random () >> 2) %
-                                              (2 * client -> interval));
+                       client->interval += random() % (2 * client->interval);
 
                /* Don't backoff past cutoff. */
-               if (client -> interval >
-                   client -> config -> backoff_cutoff)
-                       client -> interval =
-                               ((client -> config -> backoff_cutoff / 2)
-                                + ((random () >> 2) %
-                                   client -> config -> backoff_cutoff));
-       } else if (!client -> interval)
-               client -> interval = client -> config -> initial_interval;
+               if (client->interval > client->config->backoff_cutoff)
+                       client->interval = (client->config->backoff_cutoff / 2)
+                                + (random() % client->config->backoff_cutoff);
+       } else if (!client->interval)
+               client->interval = client->config->initial_interval;
                
        /* If the backoff would take us to the panic timeout, just use that
           as the interval. */
index deed7b6e1d373c11a464fd5e758d761456f22f82..a3bf741884fc304445e5fa53bab17c1307983192 100644 (file)
@@ -3,7 +3,7 @@
    Memory allocation... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: alloc.c,v 1.55 2005/03/17 20:14:56 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: alloc.c,v 1.56 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
index bdeb990ab5262556cbe900d691bde195d4c74ddc..4efae78f30226b25882cfe6382fb589c110a96bf 100644 (file)
@@ -3,7 +3,7 @@
    OMAPI object interfaces for the DHCP server. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: comapi.c,v 1.11 2005/03/17 20:14:57 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: comapi.c,v 1.12 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
index 509b9911a83fa5dcfaa6700670ca583d65d2c14c..55b8facef50f8b56854a531bb274eca090170b52 100644 (file)
@@ -3,7 +3,7 @@
    Lexical scanner for dhcpd config file... */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.95 2005/03/17 20:14:57 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.96 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -95,10 +95,14 @@ isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
 isc_result_t end_parse (cfile)
        struct parse **cfile;
 {
-       if ((*cfile) -> bufsiz)
-               dfree ((*cfile) -> inbuf, MDL);
-       dfree (*cfile, MDL);
-       *cfile = (struct parse *)0;
+       /* "Memory" config files have no file. */
+       if ((*cfile)->file != -1)
+               close((*cfile)->file);
+
+       if ((*cfile)->bufsiz)
+               dfree((*cfile)->inbuf, MDL);
+       dfree(*cfile, MDL);
+       *cfile = NULL;
        return ISC_R_SUCCESS;
 }
 
@@ -464,7 +468,7 @@ static enum dhcp_token read_number (c, cfile)
                        log_fatal("read_number():%s:%d: impossible case", MDL);
                }
 #else /* OLD_LEXER */
-               if (!seenx && (c == 'x') {
+               if (!seenx && (c == 'x')) {
                        seenx = 1;
                } else if (!isascii (c) || !isxdigit (c)) {
                        if (c != EOF) {
@@ -573,6 +577,8 @@ static enum dhcp_token intern (atom, dfv)
                        return ADDRESS;
                if (!strcasecmp (atom + 1, "ctive"))
                        return TOKEN_ACTIVE;
+               if (!strcasecmp (atom + 1, "tsfp"))
+                       return ATSFP;
                break;
              case 'b':
                if (!strcasecmp (atom + 1, "ackup"))
index 9c8a5ca4960ca71d3ac95d8c47237b42ef054b3a..16796d783de42da1f2ad413e281d01a48f267ee5 100644 (file)
@@ -3,7 +3,7 @@
    Network input dispatcher... */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: discover.c,v 1.48 2005/03/17 20:14:57 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: discover.c,v 1.49 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -463,6 +463,18 @@ void discover_interfaces (state)
 #ifdef HAVE_ARPHRD_ROSE
                      case ARPHRD_ROSE:
 #endif
+#ifdef HAVE_ARPHRD_IRDA
+                    case ARPHRD_IRDA:
+                       /* ignore infrared interfaces. */
+#endif
+#ifdef HAVE_ARPHRD_SIT
+                    case ARPHRD_SIT:
+                       /* ignore IPv6-in-IPv4 interfaces. */
+#endif
+#ifdef HAVE_ARPHRD_IEEE1394
+                    case ARPHRD_IEEE1394:
+                       /* ignore IEEE1394 interfaces. */
+#endif
 #ifdef HAVE_ARPHRD_LOOPBACK
                      case ARPHRD_LOOPBACK:
                        /* ignore loopback interface */
index ce9d1ba3b902b68964cfe85fe6cd905a0546f168..60a05251b39611dd3f5682a78d92b8c7e37c2b0c 100644 (file)
@@ -3,7 +3,7 @@
    Network input dispatcher... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dispatch.c,v 1.65 2005/03/17 20:14:57 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dispatch.c,v 1.66 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -42,7 +42,7 @@ static char copyright[] =
 struct timeout *timeouts;
 static struct timeout *free_timeouts;
 
-void set_time (u_int32_t t)
+void set_time(TIME t)
 {
        /* Do any outstanding timeouts. */
        if (cur_time != t) {
index b6ad19e253c77880807df2e6eb78d1d85f178913..fed20889327121cf27ec1773c64c4b2483c23a93 100644 (file)
@@ -3,7 +3,7 @@
    Domain Name Service subroutines. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2001-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -33,7 +33,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dns.c,v 1.37 2005/03/17 20:14:58 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dns.c,v 1.38 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -527,6 +527,7 @@ isc_result_t ddns_update_a (struct data_string *ddns_fwd_name,
        ns_updrec *updrec;
        isc_result_t result;
        char ddns_address [16];
+       const char *logstr;
 
        if (ddns_addr.len != 4)
                return ISC_R_INVALIDARG;
@@ -712,24 +713,36 @@ isc_result_t ddns_update_a (struct data_string *ddns_fwd_name,
         */
        result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue));
 
-       if (result != ISC_R_SUCCESS) {
-               if (result == YXRRSET || result == YXDOMAIN ||
-                   result == NXRRSET || result == NXDOMAIN)
-                       log_error ("Forward map from %.*s to %s already in use",
-                                  (int)ddns_fwd_name -> len,
-                                  (const char *)ddns_fwd_name -> data,
-                                  ddns_address);
-               else
-                       log_error ("Can't update forward map %.*s to %s: %s",
+       switch (result) {
+           case ISC_R_SUCCESS:
+               logstr = NULL;
+               break;
+
+           case ISC_R_YXRRSET:
+           case ISC_R_YXDOMAIN:
+               logstr = "DHCID mismatch, belongs to another client.";
+               break;
+
+           case ISC_R_NXRRSET:
+           case ISC_R_NXDOMAIN:
+               logstr = "Has an A record but no DHCID, not mine.";
+               break;
+
+           default:
+               logstr = isc_result_totext(result);
+               break;
+       }
+
+       if (logstr != NULL)
+               log_error("Forward map from %.*s to %s FAILED: %s",
                                   (int)ddns_fwd_name -> len,
                                   (const char *)ddns_fwd_name -> data,
-                                  ddns_address, isc_result_totext (result));
-
-       } else {
-               log_info ("Added new forward map from %.*s to %s",
+                                  ddns_address, logstr);
+       else
+               log_info("Added new forward map from %.*s to %s",
                          (int)ddns_fwd_name -> len,
                          (const char *)ddns_fwd_name -> data, ddns_address);
-       }
+
 #if defined (DEBUG_DNS_UPDATES)
        print_dns_status ((int)result, &updqueue);
 #endif
index cc5a6ba667c68d9026cca5ed4d0cc95a5d3a1a40..a5fc03a487f84ceed56e9898b0f26b9c9c012a58 100644 (file)
@@ -3,7 +3,7 @@
    Support for executable statements. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1998-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: execute.c,v 1.47 2005/03/17 20:14:58 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: execute.c,v 1.48 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
index 4d2914024380432ee323821a58073e060dbcc87c..28066ed06e1210b7a68ac5c5b621e9754976f221 100644 (file)
@@ -3,7 +3,7 @@
    DHCP options parsing and reassembly. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: options.c,v 1.88 2005/03/17 20:14:59 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: options.c,v 1.89 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #define DHCP_OPTION_DATA
@@ -486,7 +486,7 @@ int cons_options (inpacket, outpacket, lease, client_state,
        unsigned priority_list [PRIORITY_COUNT];
        int priority_len;
        unsigned char buffer [4096];    /* Really big buffer... */
-       unsigned main_buffer_size;
+       unsigned main_buffer_size, mb_max;
        unsigned mainbufix, bufix, agentix;
        int fileix;
        int snameix;
@@ -546,8 +546,10 @@ int cons_options (inpacket, outpacket, lease, client_state,
                main_buffer_size = 576 - DHCP_FIXED_LEN;
 
        /* Set a hard limit at the size of the output buffer. */
-       if (main_buffer_size > sizeof buffer)
-               main_buffer_size = sizeof buffer;
+       mb_max = sizeof(buffer) - (((overload & 1) ? DHCP_FILE_LEN : 0) +
+                                  ((overload & 2) ? DHCP_SNAME_LEN : 0));
+       if (main_buffer_size > mb_max)
+               main_buffer_size = mb_max;
 
        /* Preload the option priority list with mandatory options. */
        priority_len = 0;
@@ -721,14 +723,14 @@ int cons_options (inpacket, outpacket, lease, client_state,
        priority_len = 1;
        agentix +=
                store_options (0, &outpacket -> options [agentix],
-                              1500 - DHCP_FIXED_LEN - agentix,
+                              DHCP_OPTION_LEN - agentix,
                               inpacket, lease, client_state,
                               in_options, cfg_options, scope,
                               priority_list, priority_len,
                               0, 0, 0, (char *)0);
 
        /* Tack a DHO_END option onto the packet if we need to. */
-       if (agentix < 1500 - DHCP_FIXED_LEN && need_endopt)
+       if (agentix < DHCP_OPTION_LEN && need_endopt)
                outpacket -> options [agentix++] = DHO_END;
 
        /* Figure out the length. */
@@ -961,7 +963,7 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
                    unsigned incr = length;
                    int consumed = 0;
                    int *pix;
-                   char *base;
+                   unsigned char *base;
 
                    /* Try to fit it in the options buffer. */
                    if (!splitup &&
@@ -1063,6 +1065,169 @@ int store_options (ocount, buffer, buflen, packet, lease, client_state,
        return bufix;
 }
 
+/* Return true if the format string has a variable length text option
+ * ("t"), return false otherwise.
+ */
+
+int
+format_has_text(format)
+       const char *format;
+{
+       const char *p;
+       int retval = 0;
+
+       p = format;
+       while (*p != '\0') {
+               switch (*p++) {
+                   case 'd':
+                   case 't':
+                       return 1;
+
+                       /* These symbols are arbitrary, not fixed or
+                        * determinable length...text options with them is
+                        * invalid.
+                        */
+                   case 'A':
+                   case 'a':
+                   case 'X':
+                   case 'x':
+                       return 0;
+
+                       /* 'E' is variable length, but not arbitrary...you
+                        * can find its length if you can find an END option.
+                        * N is one-byte in length but trails a name of a
+                        * space defining the enumeration values.  So treat
+                        * both the same - valid, fixed-length fields.
+                        */
+                   case 'E':
+                   case 'N':
+                       /* Consume the space name. */
+                       while ((*p != '\0') && (*p++ != '.'))
+                               ;
+                       break;
+
+                   default:
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+/* Determine the minimum length of a DHCP option prior to any variable
+ * or inconsistent length formats, according to its configured format
+ * variable (and possibly from supplied option cache contents for variable
+ * length format symbols).
+ */
+
+int
+format_min_length(format, oc)
+       const char *format;
+       struct option_cache *oc;
+{
+       const char *p;
+       int min_len = 0;
+       int last_size = 0;
+
+       p = format;
+       while (*p != '\0') {
+               switch (*p++) {
+                   case 'I': /* IPv4 Address */
+                   case 'l': /* int32_t */
+                   case 'L': /* uint32_t */
+                   case 'T': /* Lease Time, uint32_t equivalent */
+                       min_len += 4;
+                       last_size = 4;
+                       break;
+
+                   case 's': /* int16_t */
+                   case 'S': /* uint16_t */
+                       min_len += 2;
+                       last_size = 2;
+                       break;
+
+                   case 'N': /* Enumeration in 1-byte values. */
+                       /* Consume space name. */
+                       while ((*p != '\0') && (*p++ != '.'))
+                               ;
+
+                       /* Fall Through to handle as one-byte field */
+
+                   case 'b': /* int8_t */
+                   case 'B': /* uint8_t */
+                   case 'F': /* Flag that is always true. */
+                   case 'f': /* Flag */
+                       min_len++;
+                       last_size = 1;
+                       break;
+
+                   case 'o': /* Last argument is optional. */
+                       min_len -= last_size;
+                   case 'e': /* Encapsulation hint (there is an 'E' later). */
+                       last_size = 0;
+                       break;
+
+                   case 'E': /* Encapsulated options. */
+                       /* Consume space name. */
+                       while ((*p != '\0') && (*p++ != '.'))
+                               ;
+
+                       /* Find an end option, or find that the encaps options
+                        * go all the way to the end (or beyond) of the data
+                        * portion of the option.
+                        */
+                       last_size = 0;
+                       while (min_len < oc->data.len) {
+                               if (oc->data.data[min_len] == DHO_END) {
+                                       min_len++;
+                                       last_size++;
+                                       break;
+                               } else if (oc->data.data[min_len] == DHO_PAD) {
+                                       min_len++;
+                                       last_size++;
+                               } else if ((min_len + 1) < oc->data.len) {
+                                       min_len += oc->data.data[min_len+1]+2;
+                                       last_size += oc->data.data[min_len+1]+2;
+                               } else {
+                                       /* Suboption length is out of bounds,
+                                        * advance beyond the code/length pair
+                                        * to trigger below error conditonal.
+                                        */
+                                       min_len += 2;
+                                       last_size += 2;
+                                       break;
+                               }
+                       }
+
+                       if (min_len > oc->data.len) {
+                               log_error("format_min_length(%s): "
+                                         "Encapsulated options exceed "
+                                         "supplied buffer.", format);
+                               return INT_MAX;
+                       }
+
+                       break;
+
+                   case 'd': /* "Domain name" */
+                   case 't': /* "ASCII Text" */
+                   case 'X': /* "ASCII or Hex Conditional */
+                   case 'x': /* "Hex" */
+                   case 'A': /* Array of all that precedes. */
+                   case 'a': /* Array of preceding symbol. */
+                       return min_len;
+
+                   default:
+                       /* No safe value is known. */
+                       log_error("format_min_length(%s): No safe value "
+                                 "for unknown format symbols.", format);
+                       return INT_MAX;
+               }
+       }
+
+       return min_len;
+}
+
+
 /* Format the specified option so that a human can easily read it. */
 
 const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
@@ -1517,6 +1682,21 @@ int save_option_buffer (struct universe *universe,
        
        op -> option = option;
 
+       /* If this option is ultimately a text option, null determinate to
+        * comply with RFC2132 section 2.  Mark a flag so this can be sensed
+        * later to echo NULLs back to clients that supplied them (they
+        * probably expect them).
+        */
+       if (format_has_text(option->format)) {
+               int min_len = format_min_length(option->format, op);
+
+               while ((op->data.len > min_len) &&
+                      (op->data.data[op->data.len-1] == '\0')) {
+                       op->data.len--;
+                       op->flags |= OPTION_HAD_NULLS;
+               }
+       }
+
        /* Now store the option. */
        save_option (universe, options, op);
 
index 7b425f0977f00d8e233a02be3a54bbc7321b529f..9882c150f9db94365afe5fa91925d319ddeea4bf 100644 (file)
@@ -3,7 +3,7 @@
    Common parser code for dhcpd and dhclient. */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.106 2005/03/17 20:14:59 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.107 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -405,6 +405,7 @@ void parse_lease_time (cfile, timep)
 {
        const char *val;
        enum dhcp_token token;
+       u_int32_t num;
 
        token = next_token (&val, (unsigned *)0, cfile);
        if (token != NUMBER) {
@@ -412,9 +413,9 @@ void parse_lease_time (cfile, timep)
                skip_to_semi (cfile);
                return;
        }
-       convert_num (cfile, (unsigned char *)timep, val, 10, 32);
+       convert_num(cfile, (unsigned char *)&num, val, 10, 32);
        /* Unswap the number - convert_num returns stuff in NBO. */
-       *timep = ntohl (*timep); /* XXX */
+       *timep = ntohl(num);
 
        parse_semi (cfile);
 }
index f46d8c559ff227b3b8534a7c80f622b751de1a54..60e029b7ec716ff0e7086c06cbcfea994039c074 100644 (file)
@@ -3,7 +3,7 @@
    Turn data structures into printable text. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: print.c,v 1.57 2005/03/17 20:14:59 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: print.c,v 1.58 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
index 61ff3a7d6e2a7f41d9bffb7cdaa38a15d98b94b1..5f34f78bf2fad798f930663823ffd087740abb1e 100644 (file)
@@ -3,7 +3,7 @@
    Parser for /etc/resolv.conf file. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: resolv.c,v 1.17 2005/03/17 20:15:00 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: resolv.c,v 1.18 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -172,7 +172,6 @@ void read_resolv_conf (parse_time)
                } else
                        dl = dp;
        }
-       close (file);
        end_parse (&cfile);
 }
 
index 66021bb8761ad50b965fe99f67639c205468b713..6f177b0b54d663eb7f733b5482cdb8e92ff0a3bd 100644 (file)
@@ -3,7 +3,7 @@
    Tables of information... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tables.c,v 1.53 2005/03/17 20:15:00 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tables.c,v 1.54 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -58,6 +58,9 @@ HASH_FUNCTIONS (option, const char *, struct option, option_hash_t, 0, 0)
    b - 8-bit signed integer
    B - 8-bit unsigned integer
    t - ASCII text
+   T - Lease Time, 32-bit unsigned integer implying a number of seconds from
+       some event.  The special all-ones value means 'infinite'.  May either
+       be printed as a decimal, eg, "3600", or as this name, eg, "infinite".
    f - flag (true or false)
    A - array of whatever precedes (e.g., IA means array of IP addresses)
    a - array of the preceding character (e.g., IIa means two or more IP
@@ -102,7 +105,7 @@ struct option dhcp_options [256] = {
        { "lpr-servers", "IA",                          &dhcp_universe, 9 },
        { "impress-servers", "IA",                      &dhcp_universe, 10 },
        { "resource-location-servers", "IA",            &dhcp_universe, 11 },
-       { "host-name", "X",                             &dhcp_universe, 12 },
+       { "host-name", "t",                             &dhcp_universe, 12 },
        { "boot-size", "S",                             &dhcp_universe, 13 },
        { "merit-dump", "t",                            &dhcp_universe, 14 },
        { "domain-name", "t",                           &dhcp_universe, 15 },
@@ -152,7 +155,7 @@ struct option dhcp_options [256] = {
        { "dhcp-rebinding-time", "L",                   &dhcp_universe, 59 },
        { "vendor-class-identifier", "X",               &dhcp_universe, 60 },
        { "dhcp-client-identifier", "X",                &dhcp_universe, 61 },
-       { "nwip-domain", "X",                           &dhcp_universe, 62 },
+       { "nwip-domain", "t",                           &dhcp_universe, 62 },
        { "nwip-suboptions", "Enwip.",                  &dhcp_universe, 63 },
        { "nisplus-domain", "t",                        &dhcp_universe, 64 },
        { "nisplus-servers", "IA",                      &dhcp_universe, 65 },
@@ -176,8 +179,8 @@ struct option dhcp_options [256] = {
        { "unknown-83", "X",                            &dhcp_universe, 83 },
        { "unknown-84", "X",                            &dhcp_universe, 84 },
        { "nds-servers", "IA",                          &dhcp_universe, 85 },
-       { "nds-tree-name", "X",                         &dhcp_universe, 86 },
-       { "nds-context", "X",                           &dhcp_universe, 87 },
+       { "nds-tree-name", "t",                         &dhcp_universe, 86 },
+       { "nds-context", "t",                           &dhcp_universe, 87 },
        { "unknown-88", "X",                            &dhcp_universe, 88 },
        { "unknown-89", "X",                            &dhcp_universe, 89 },
        { "unknown-90", "X",                            &dhcp_universe, 90 },
@@ -208,7 +211,7 @@ struct option dhcp_options [256] = {
        { "unknown-115", "X",                           &dhcp_universe, 115 },
        { "unknown-116", "X",                           &dhcp_universe, 116 },
        { "unknown-117", "X",                           &dhcp_universe, 117 },
-       { "subnet-selection", "X",                      &dhcp_universe, 118 },
+       { "subnet-selection", "I",                      &dhcp_universe, 118 },
        { "unknown-119", "X",                           &dhcp_universe, 119 },
        { "unknown-120", "X",                           &dhcp_universe, 120 },
        { "unknown-121", "X",                           &dhcp_universe, 121 },
@@ -608,6 +611,15 @@ struct option nwip_options [256] = {
        { "unknown-end", "e",                           &nwip_universe, 255 },
 };
 
+/* Note that the "FQDN suboption space" does not reflect the FQDN option
+ * format - rather, this is a handy "virtualization" of a flat option
+ * which makes manual configuration and presentation of some of its
+ * contents easier (each of these suboptions is a fixed-space field within
+ * the fqdn contents - domain and host names are derived from a common field,
+ * and differ in the left and right hand side of the leftmost dot, fqdn is
+ * the combination of the two).
+ */
+
 struct universe fqdn_universe;
 struct option fqdn_options [256] = {
        { "pad", "",                                    &fqdn_universe, 0 },
index f653ed6ceefefac3e7a69ec847f217d303d2f057..b246b11399da430e5867956fffe046b28d92bec1 100644 (file)
@@ -4,7 +4,7 @@
    Contributed in May of 1999 by Andrew Chittenden */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -28,7 +28,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tr.c,v 1.8 2005/03/17 20:15:01 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tr.c,v 1.9 2006/02/24 23:16:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,8 +59,8 @@ struct routing_entry {
         struct routing_entry *next;
         unsigned char addr[TR_ALEN];
         unsigned char iface[5];
-        __u16 rcf;                      /* route control field */
-        __u16 rseg[8];                  /* routing registers */
+        u_int16_t rcf;                      /* route control field */
+        u_int16_t rseg[8];                  /* routing registers */
         unsigned long access_time;      /* time we last used this entry */
 };
 
@@ -217,7 +217,7 @@ static int insert_source_routing (trh, interface)
                if (rover != NULL) {
                         /* success: route that frame */
                         if ((rover->rcf & TR_RCF_LEN_MASK) >> 8) {
-                                __u16 rcf = rover->rcf;
+                                u_int16_t rcf = rover->rcf;
                                memcpy(trh->rseg,rover->rseg,sizeof(trh->rseg));
                                rcf ^= TR_RCF_DIR_BIT;  
                                rcf &= ~TR_RCF_BROADCAST_MASK;
@@ -254,7 +254,7 @@ static void save_source_routing(trh, interface)
         struct routing_entry *rover;
         struct timeval now;
         unsigned char saddr[TR_ALEN];
-        __u16 rcf = 0;
+        u_int16_t rcf = 0;
 
         gettimeofday(&now, NULL);
 
index b302a3633c08adef43826f9cb5103e7a81113a50..e19886415cb35f0b313861941598e80ce65cb6ac 100644 (file)
@@ -3,7 +3,7 @@
    Routines for manipulating parse trees... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tree.c,v 1.103 2005/03/17 20:15:01 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tree.c,v 1.104 2006/02/24 23:16:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
index bf28ed49df54a3fbd17599ff1c2bd1a6ee9f4d8e..afac88ac705877b5b04eb7b6174b1d25b1ce088a 100644 (file)
@@ -3,7 +3,7 @@
    Examine and modify omapi objects. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2001-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: omshell.c,v 1.10 2005/03/17 20:15:04 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: omshell.c,v 1.11 2006/02/24 23:16:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include <time.h>
@@ -180,7 +180,7 @@ int main (int argc, char **argv, char **envp)
            if (fgets (buf, sizeof(buf), stdin) == NULL)
                break;
 
-           status = new_parse (&cfile, 0, buf, strlen(buf), "<STDIN>", 1);
+           status = new_parse (&cfile, -1, buf, strlen(buf), "<STDIN>", 1);
            check(status, "new_parse()");
            
            token = next_token (&val, (unsigned *)0, cfile);
index 6cefbd0e8a8af28a22c3ba87bfc6e77d2210dbed..1028a9ca41ee8664ad9c500b2eada093c94a0315 100644 (file)
@@ -5,7 +5,7 @@
    Based on a configuration originally supplied by Jonathan Stone. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -98,6 +98,11 @@ extern int h_errno;
 
 #define VOIDPTR        void *
 
+#if defined(__alpha__) || defined(__amd64__) || defined(__ia64__) || \
+       defined(__sparc64__)
+# define PTRSIZE_64BIT
+#endif
+
 #define EOL    '\n'
 
 /* Time stuff... */
@@ -108,7 +113,7 @@ extern int h_errno;
 #define GET_TIME(x)    time ((x))
 
 #if (LINUX_MAJOR >= 2)
-# if (LINUX_MINOR >= 1)
+# if ((LINUX_MAJOR > 2) || (LINUX_MINOR >= 1))
 #  if defined (USE_DEFAULT_NETWORK)
 #   define USE_LPF
 #  endif
index 8a1e416bc18bb261146e12beb7fed00e7e36ce6c..e9789d60a686c162db4f82e46fe008539b5dd11e 100644 (file)
@@ -3,7 +3,7 @@
    System dependencies for Solaris 2.x (tested on 2.5 with gcc)... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
 
 /* SunOS defines uint*_t and int*_t, but not u_int*_t.  */
 
+#if defined(_SYS_INT_TYPES_H)
 typedef uint8_t                u_int8_t;
 typedef uint16_t       u_int16_t;
 typedef uint32_t       u_int32_t;
+#else /* Older SunOS has no idea what these things mean. */
+typedef int8_t char
+typedef int16_t short
+typedef int32_t int    /* If _LP64, long is 64-bit, int is still 32. */
+typedef u_int8_t unsigned char
+typedef u_int16_t unsigned short
+typedef u_int32_t unsigned int
+#endif /* defined(_SYS_INT_TYPES_H) */
 
 /* The jmp_buf type is an array on Solaris, so we can't dereference it
    and must declare it differently. */
index 76dd07bb410a3873ccf9d3bd72a098a7c4959efc..38a594ead76f7c5cb4c02bfcbcdcb5dad2fdb8bb 100644 (file)
@@ -3,7 +3,7 @@
    Protocol structures... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -30,8 +30,7 @@
  * To learn more about Vixie Enterprises, see ``http://www.vix.com''.
  */
 
-#define DHCP_UDP_OVERHEAD      (14 + /* Ethernet header */             \
-                                20 + /* IP header */                   \
+#define DHCP_UDP_OVERHEAD      (20 + /* IP header */                   \
                                 8)   /* UDP header */
 #define DHCP_SNAME_LEN         64
 #define DHCP_FILE_LEN          128
index dc3f52e8f73036c23790548e4ea6f17e7625155c..d9c911fcec0e6ca54a2d81b89032e0c48a2f19be 100644 (file)
@@ -187,6 +187,9 @@ struct option_cache {
        struct expression *expression;
        struct option *option;
        struct data_string data;
+
+       #define OPTION_HAD_NULLS        0x00000001
+       u_int32_t flags;
 };
 
 struct option_state {
@@ -313,8 +316,15 @@ struct lease {
        
        struct lease_state *state;
 
+       /* 'tsfp' is more of an 'effective' tsfp.  It may be calculated from
+        * stos+mclt for example if it's an expired lease and the server is
+        * in partner-down state.  'atsfp' is zeroed whenever a lease is
+        * updated - and only set when the peer acknowledges it.  This
+        * ensures every state change is transmitted.
+        */
        TIME tstp;      /* Time sent to partner. */
        TIME tsfp;      /* Time sent from partner. */
+       TIME atsfp;     /* Actual time sent from partner. */
        TIME cltt;      /* Client last transaction time. */
        struct lease *next_pending;
 };
@@ -331,7 +341,7 @@ struct lease_state {
        struct option_state *options;
        struct data_string parameter_request_list;
        int max_message_size;
-       u_int32_t expiry, renewal, rebind;
+       TIME expiry, renewal, rebind;
        struct data_string filename, server_name;
        int got_requested_address;
        int got_server_identifier;
@@ -993,6 +1003,8 @@ int store_options PROTO ((int *, unsigned char *, unsigned, struct packet *,
                          struct option_state *, struct binding_scope **,
                          unsigned *, int, unsigned, unsigned,
                          int, const char *));
+int format_has_text(const char *);
+int format_min_length(const char *, struct option_cache *);
 const char *pretty_print_option PROTO ((struct option *, const unsigned char *,
                                        unsigned, int, int));
 int get_option (struct data_string *, struct universe *,
@@ -1769,7 +1781,7 @@ int if_readsocket PROTO ((omapi_object_t *));
 void reinitialize_interfaces PROTO ((void));
 
 /* dispatch.c */
-void set_time (u_int32_t);
+void set_time(TIME);
 struct timeval *process_outstanding_timeouts (struct timeval *);
 void dispatch PROTO ((void));
 isc_result_t got_one PROTO ((omapi_object_t *));
index 858e3c989b264ba16bc7c9d881cc55f081cae1fd..da8da3d429adc33517b31e49862d4f8a896af08b 100644 (file)
@@ -308,7 +308,8 @@ enum dhcp_token {
        REFRESH = 612,
        DOMAIN_NAME = 613,
        DO_FORWARD_UPDATE = 614,
-       KNOWN_CLIENTS = 615
+       KNOWN_CLIENTS = 615,
+       ATSFP = 616
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index d48c3700ea30da98c648d79ccd430b34c6703a6c..028798f8ad4721934a96143cc52a965efbde90dd 100644 (file)
@@ -3,7 +3,7 @@
    Definitions for omapi tracing facility... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2001-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -90,7 +90,7 @@ typedef struct {
 void trace_free_all (void);
 int trace_playback (void);
 int trace_record (void);
-isc_result_t trace_init (void (*set_time) (u_int32_t), const char *, int);
+isc_result_t trace_init (void (*set_time) (TIME), const char *, int);
 isc_result_t trace_begin (const char *, const char *, int);
 isc_result_t trace_write_packet (trace_type_t *, unsigned, const char *,
                                 const char *, int);
index 5d1bc912cfc6eeebbcca052c3c3851b17ecf0716..d5f47a765310803f62a75f18f84f05a32221723e 100644 (file)
@@ -3,7 +3,7 @@
    Operating system dependencies... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
 # define HAVE_ARPHRD_ROSE
 #endif
 
+#if defined (ARPHRD_IRDA) && !defined (HAVE_ARPHRD_IRDA)
+# define HAVE_ARPHRD_IRDA
+#endif
+
+#if defined (ARPHRD_SIT) && !defined (HAVE_ARPHRD_SIT)
+# define HAVE_ARPHRD_SIT
+#endif
+
+#if defined (ARPHRD_IEEE1394) & !defined (HAVE_ARPHRD_IEEE1394)
+# define HAVE_ARPHRD_IEEE1394
+#endif
+
 #if defined (ARPHRD_IEEE802) && !defined (HAVE_ARPHRD_IEEE802)
 # define HAVE_ARPHRD_IEEE802
 #endif
index 46c0bc389501ab49e9c73da9957da1ac9fa249a9..c1c472833a5244f10df895f6f09962f945c9a3b4 100644 (file)
@@ -4,7 +4,7 @@
    protocol... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char copyright[] =
+"$Id: alloc.c,v 1.26 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium, Inc.  All rights reserved.\n";
+#endif /* not lint */
+
 #include <omapip/omapip_p.h>
 
 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
@@ -59,13 +64,21 @@ VOIDPTR dmalloc (size, file, line)
        const char *file;
        int line;
 {
-       unsigned char *foo = malloc (size + DMDSIZE);
+       unsigned char *foo;
+       unsigned len;
        int i;
        VOIDPTR *bar;
 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
                defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
        struct dmalloc_preamble *dp;
 #endif
+
+       len = size + DMDSIZE;
+       if (len < size)
+               return (VOIDPTR)0;
+
+       foo = malloc(len);
+
        if (!foo)
                return (VOIDPTR)0;
        bar = (VOIDPTR)(foo + DMDOFFSET);
@@ -804,10 +817,18 @@ isc_result_t omapi_typed_data_new (const char *file, int line,
                s = va_arg (l, char *);
                val = strlen (s);
                len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
+               if (len < val) {
+                       va_end(l);
+                       return ISC_R_INVALIDARG;
+               }
                break;
              case omapi_datatype_data:
                val = va_arg (l, unsigned);
                len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
+               if (len < val) {
+                       va_end(l);
+                       return ISC_R_INVALIDARG;
+               }
                break;
              case omapi_datatype_object:
                len = OMAPI_TYPED_DATA_OBJECT_LEN;
@@ -923,8 +944,12 @@ isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len,
                                    const char *file, int line)
 {
        omapi_data_string_t *new;
+       unsigned nlen;
 
-       new = dmalloc (OMAPI_DATA_STRING_EMPTY_SIZE + len, file, line);
+       nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len;
+       if (nlen < len)
+               return ISC_R_INVALIDARG;
+       new = dmalloc (nlen, file, line);
        if (!new)
                return ISC_R_NOMEMORY;
        memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE);
index ac92afc1ced339e65f2a6c983bb62a8b3fc723da..246d9b78b1e17bbe96065649a8457ab048561f68 100644 (file)
@@ -3,7 +3,7 @@
    Subroutines that support the omapi extensible array type. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2001-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char ocopyright[] =
+"$Id: array.c,v 1.4 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+#endif
+
 #include <omapip/omapip_p.h>
 
 /* Allocate a new extensible array. */
index 74f53dae68fab5c134c833aebcfe57845fc1da22..6b751effe893ec0b31ef9bc5752c0f9d1e7fca6a 100644 (file)
@@ -3,7 +3,7 @@
    Buffer access functions for the object management protocol... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -154,10 +154,6 @@ static isc_result_t omapi_connection_reader_trace (omapi_object_t *h,
                return ISC_R_INVALIDARG;
        c = (omapi_connection_object_t *)h;
 
-       /* Make sure c -> bytes_needed is valid. */
-       if (c -> bytes_needed < 0)
-               return ISC_R_INVALIDARG;
-       
        /* See if there are enough bytes. */
        if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
            c -> in_bytes > c -> bytes_needed)
index 8b9446f97e9f932ab7a6446e73ad5219ad5aac57..aaf0058c8d3b4482a3f425d3a6d11dfc0a3fba5e 100644 (file)
@@ -3,7 +3,7 @@
    Subroutines that support the generic object. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char ocopyright[] =
+"$Id: generic.c,v 1.12 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+#endif
+
 #include <omapip/omapip_p.h>
 
 OMAPI_OBJECT_ALLOC (omapi_generic,
index cffa4d6094811ed2c0b0cc6b23a394a6d30fba9c..e1298354461ac5c231d01561857181728bb80d6e 100644 (file)
@@ -3,7 +3,7 @@
    Functions for maintaining handles on objects. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char ocopyright[] =
+"$Id: handle.c,v 1.8 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+#endif
+
 #include <omapip/omapip_p.h>
 
 /* The handle table is a hierarchical tree designed for quick mapping
index 1bd5e124a77807179b94d39d27c71a31a6f65692..4b1833b9c17c0b1717248903ff682119a15d6fd8 100644 (file)
@@ -3,7 +3,7 @@
    Routines for manipulating hash tables... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: hash.c,v 1.6 2005/09/30 17:57:32 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: hash.c,v 1.7 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include <omapip/omapip_p.h>
index a9d76f753fe9f9d5521c2883ce640bd8df4a4d56..f5bbb0c7c94e2ec0d1f9bf2e5c1c366b6f1c64e7 100644 (file)
@@ -3,7 +3,7 @@
    Functions supporting the object management protocol... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char ocopyright[] =
+"$Id: protocol.c,v 1.30 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+#endif
+
 #include <omapip/omapip_p.h>
 
 OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
index 4efde414d75efdcb96965483d2999fc23d88c2f3..4f5538ecc44d02bf18657314ab314f465299b6f9 100644 (file)
@@ -3,7 +3,7 @@
    Subroutines providing general support for objects. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char ocopyright[] =
+"$Id: support.c,v 1.28 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+#endif
+
 #include <omapip/omapip_p.h>
 
 omapi_object_type_t *omapi_type_connection;
index 9245d27a37544bd8edbf1d3b371f51bad159f1b6..8d3ce62349892b9db9f5ff19bf09159d023e94e8 100644 (file)
@@ -5,7 +5,7 @@
    transactions... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2001-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
  * learn more about Nominum, Inc., see ``http://www.nominum.com''.
  */
 
+#ifndef lint
+static char ocopyright[] =
+"$Id: trace.c,v 1.12 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+#endif
+
 #include <omapip/omapip_p.h>
 
 #if defined (TRACING)
-void (*trace_set_time_hook) (u_int32_t);
+void (*trace_set_time_hook) (TIME);
 static int tracing_stopped;
 static int traceoutfile;
 static int traceindex;
@@ -97,7 +102,7 @@ int trace_record ()
        return 0;
 }
 
-isc_result_t trace_init (void (*set_time) (u_int32_t),
+isc_result_t trace_init (void (*set_time) (TIME),
                         const char *file, int line)
 {
        trace_type_t *root_type;
@@ -136,7 +141,7 @@ isc_result_t trace_begin (const char *filename,
                return ISC_R_INVALIDARG;
        }
 
-       traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0644);
+       traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
        if (traceoutfile < 0) {
                log_error ("%s(%d): trace_begin: %s: %m",
                           file, line, filename);
index a6ec87b1c4a0a8ea96a680f1ad77f0e9d140f3a6..452724b10b6553a72dd86ee676517c68aea4d953 100644 (file)
@@ -3,7 +3,7 @@
    DHCP/BOOTP Relay Agent. */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1997-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhcrelay.c,v 1.53 2005/03/17 20:15:24 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhcrelay.c,v 1.54 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -537,7 +537,7 @@ int strip_relay_agent_options (in, out, packet, length)
        unsigned length;
 {
        int is_dhcp = 0;
-       u_int8_t *op, *sp, *max;
+       u_int8_t *op, *nextop, *sp, *max;
        int good_agent_option = 0;
        int status;
 
@@ -583,6 +583,13 @@ int strip_relay_agent_options (in, out, packet, length)
                        if (!is_dhcp)
                                goto skip;
 
+                       /* Do not process an agent option if it exceeds the
+                        * buffer.  Fail this packet.
+                        */
+                       nextop = op + op[1] + 2;
+                       if (nextop > max)
+                               return 0;
+
                        status = find_interface_by_agent_option (packet,
                                                                 out, op + 2,
                                                                 op [1]);
@@ -590,16 +597,26 @@ int strip_relay_agent_options (in, out, packet, length)
                                return 0;
                        if (status)
                                good_agent_option = 1;
-                       op += op [1] + 2;
+                       op = nextop;
                        break;
 
                      skip:
                        /* Skip over other options. */
                      default:
-                       if (sp != op)
-                               memcpy (sp, op, (unsigned)(op [1] + 2));
-                       sp += op [1] + 2;
-                       op += op [1] + 2;
+                       /* Fail if processing this option will exceed the
+                        * buffer (op[1] is malformed).
+                        */
+                       nextop = op + op[1] + 2;
+                       if (nextop > max)
+                               return 0;
+
+                       if (sp != op) {
+                               memmove(sp, op, op[1] + 2);
+                               sp += op[1] + 2;
+                               op = nextop;
+                       } else
+                               op = sp = nextop;
+
                        break;
                }
        }
@@ -627,7 +644,7 @@ int strip_relay_agent_options (in, out, packet, length)
                /* Make sure the packet isn't short (this is unlikely,
                    but WTH) */
                if (length < BOOTP_MIN_LEN) {
-                       memset (sp, 0, BOOTP_MIN_LEN - length);
+                       memset (sp, DHO_PAD, BOOTP_MIN_LEN - length);
                        length = BOOTP_MIN_LEN;
                }
        }
@@ -718,7 +735,8 @@ int add_relay_agent_options (ip, packet, length, giaddr)
        struct in_addr giaddr;
 {
        int is_dhcp = 0, agent_options_present = 0;
-       u_int8_t *op, *sp, *max, *end_pad = 0;
+       unsigned optlen;
+       u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
 
        /* If we're not adding agent options to packets, we can skip
           this. */
@@ -727,21 +745,35 @@ int add_relay_agent_options (ip, packet, length, giaddr)
 
        /* If there's no cookie, it's a bootp packet, so we should just
           forward it unchanged. */
-       if (memcmp (packet -> options, DHCP_OPTIONS_COOKIE, 4))
+       if (memcmp(packet->options, DHCP_OPTIONS_COOKIE, 4))
                return length;
 
        max = ((u_int8_t *)packet) + length;
-       sp = op = &packet -> options [4];
+
+       /* Commence processing after the cookie. */
+       sp = op = &packet->options[4];
 
        while (op < max) {
                switch (*op) {
                        /* Skip padding... */
                      case DHO_PAD:
-                       end_pad = sp;
+                       /* Remember the first pad byte so we can commandeer
+                        * padded space.
+                        *
+                        * XXX: Is this really a good idea?  Sure, we can
+                        * seemingly reduce the packet while we're looking,
+                        * but if the packet was signed by the client then
+                        * this padding is part of the checksum (RFC3118),
+                        * and its nonpresence would break authentication.
+                        */
+                       if (end_pad == NULL)
+                               end_pad = sp;
+
                        if (sp != op)
-                               *sp = *op;
-                       ++op;
-                       ++sp;
+                               *sp++ = *op++;
+                       else
+                               sp = ++op;
+
                        continue;
 
                        /* If we see a message type, it's a DHCP packet. */
@@ -760,7 +792,8 @@ int add_relay_agent_options (ip, packet, length, giaddr)
                           but if we do, we have to leave it alone. */
                        if (!is_dhcp)
                                goto skip;
-                       end_pad = 0;
+
+                       end_pad = NULL;
 
                        /* There's already a Relay Agent Information option
                           in this packet.   How embarrassing.   Decide what
@@ -780,17 +813,28 @@ int add_relay_agent_options (ip, packet, length, giaddr)
 
                        /* Skip over the agent option and start copying
                           if we aren't copying already. */
-                       op += op [1] + 2;
+                       op += op[1] + 2;
                        break;
 
                      skip:
                        /* Skip over other options. */
                      default:
-                       end_pad = 0;
-                       if (sp != op)
-                               memcpy (sp, op, (unsigned)(op [1] + 2));
-                       sp += op [1] + 2;
-                       op += op [1] + 2;
+                       /* Fail if processing this option will exceed the
+                        * buffer (op[1] is malformed).
+                        */
+                       nextop = op + op[1] + 2;
+                       if (nextop > max)
+                               return 0;
+
+                       end_pad = NULL;
+
+                       if (sp != op) {
+                               memmove(sp, op, op[1] + 2);
+                               sp += op[1] + 2;
+                               op = nextop;
+                       } else
+                               op = sp = nextop;
+
                        break;
                }
        }
@@ -803,50 +847,56 @@ int add_relay_agent_options (ip, packet, length, giaddr)
        /* If the packet was padded out, we can store the agent option
           at the beginning of the padding. */
 
-       if (end_pad)
+       if (end_pad != NULL)
                sp = end_pad;
 
        /* Remember where the end of the packet was after parsing
           it. */
        op = sp;
 
-       /* XXX Is there room? */
+       /* Sanity check.  Had better not ever happen. */
+       if ((ip->circuit_id_len > 255) || (ip->circuit_id_len < 1))
+               log_fatal("circuit id length %d out of range [1-255] on "
+                         "%s\n", ip->circuit_id_len, ip->name);
+       optlen = ip->circuit_id_len + 2;            /* RAI_CIRCUIT_ID + len */
+
+       if (ip->remote_id) {
+               if (ip->remote_id_len > 255 || ip->remote_id_len < 1)
+                       log_fatal("remote id length %d out of range [1-255] "
+                                 "on %s\n", ip->circuit_id_len, ip->name);
+               optlen += ip->remote_id_len + 2;    /* RAI_REMOTE_ID + len */
+       }
+
+       /* We do not support relay option fragmenting (multiple options to
+        * support an option data exceeding 255 bytes).
+        */
+       if ((optlen < 3) || (optlen > 255))
+               log_fatal ("total agent option length (%u) out of range "
+                          "[3 - 255] on %s\n", optlen, ip->name);
+
+       /* Is there room for the option, its code+len, and DHO_END? */
+       if ((sp > max) || (max - sp < optlen + 3))
+               return 0;
 
        /* Okay, cons up *our* Relay Agent Information option. */
        *sp++ = DHO_DHCP_AGENT_OPTIONS;
-       *sp++ = 0;      /* Dunno... */
+       *sp++ = optlen;
 
        /* Copy in the circuit id... */
        *sp++ = RAI_CIRCUIT_ID;
-       /* Sanity check.   Had better not every happen. */
-       if (ip -> circuit_id_len > 255 || ip -> circuit_id_len < 1)
-               log_fatal ("completely bogus circuit id length %d on %s\n",
-                      ip -> circuit_id_len, ip -> name);
-       *sp++ = ip -> circuit_id_len;
-       memcpy (sp, ip -> circuit_id, ip -> circuit_id_len);
-       sp += ip -> circuit_id_len;
+       *sp++ = ip->circuit_id_len;
+       memcpy(sp, ip->circuit_id, ip->circuit_id_len);
+       sp += ip->circuit_id_len;
 
        /* Copy in remote ID... */
-       if (ip -> remote_id) {
+       if (ip->remote_id) {
                *sp++ = RAI_REMOTE_ID;
-               if (ip -> remote_id_len > 255 || ip -> remote_id_len < 1)
-                       log_fatal ("bogus remote id length %d on %s\n",
-                              ip -> circuit_id_len, ip -> name);
-               *sp++ = ip -> remote_id_len;
-               memcpy (sp, ip -> remote_id, ip -> remote_id_len);
-               sp += ip -> remote_id_len;
+               *sp++ = ip->remote_id_len;
+               memcpy(sp, ip->remote_id, ip->remote_id_len);
+               sp += ip->remote_id_len;
        }
 
-       /* Relay option's total length shouldn't ever get to be more than
-          257 bytes. */
-       if (sp - op > 257)
-           log_fatal ("total agent option length exceeds 257 (%ld) on %s\n",
-                      (long)(sp - op), ip -> name);
-
-       /* Calculate length of RAI option. */
-       op [1] = sp - op - 2;
-
-       /* Deposit an END token. */
+       /* Deposit an END option. */
        *sp++ = DHO_END;
 
        /* Recalculate total packet length. */
@@ -854,8 +904,8 @@ int add_relay_agent_options (ip, packet, length, giaddr)
 
        /* Make sure the packet isn't short (this is unlikely, but WTH) */
        if (length < BOOTP_MIN_LEN) {
-               memset (sp, 0, BOOTP_MIN_LEN - length);
-               length = BOOTP_MIN_LEN;
+               memset(sp, DHO_PAD, BOOTP_MIN_LEN - length);
+               return BOOTP_MIN_LEN;
        }
 
        return length;
index b66567e142b94fa933d74c0c1ec1e807f32559cc..e17e8ba55c9a7a5267b3f6b9ad64b562245d5ed3 100644 (file)
@@ -3,7 +3,7 @@
    Parser for dhcpd config file... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.149 2005/09/30 17:57:32 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.150 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -162,7 +162,6 @@ isc_result_t read_conf_file (const char *filename, struct group *group,
        new_parse (&cfile, -1, fbuf, ulen, filename, 0); /* XXX */
 #else
        new_parse (&cfile, file, (char *)0, 0, filename, 0);
-       close (file);
 #endif
        if (leasep)
                status = lease_file_subparse (cfile);
@@ -2624,6 +2623,7 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
                      case TIMESTAMP:
                      case TSTP:
                      case TSFP:
+                     case ATSFP:
                      case CLTT:
                        t = parse_date (cfile);
                        switch (token) {
@@ -2651,6 +2651,11 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
                                seenbit = 131072;
                                lease -> tsfp = t;
                                break;
+
+                             case ATSFP:
+                               seenbit = 262144;
+                               lease->atsfp = t;
+                               break;
                                
                              case CLTT:
                                seenbit = 524288;
index 8006600750bd5ad1158dbb47dec162c155cc6adf..55302820f6bda31267e318f9af48a8318a1e014b 100644 (file)
@@ -3,7 +3,7 @@
    Persistent database management routines for DHCPD... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: db.c,v 1.69 2005/09/30 17:57:32 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: db.c,v 1.70 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -133,6 +133,14 @@ int write_lease (lease)
                        ++errors;
                }
        }
+       if (lease->atsfp) {
+               t = gmtime(&lease->atsfp);
+               if (fprintf(db_file,
+                           "\n  atsfp %d %d/%02d/%02d %02d:%02d:%02d;",
+                           t->tm_wday, t->tm_year + 1900, t->tm_mon + 1,
+                           t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec) <= 0)
+                       ++errors;
+       }
        if (lease -> cltt) {
                t = gmtime (&lease -> cltt);
                errno = 0;
@@ -848,12 +856,7 @@ int new_lease_file ()
        char backfname [512];
        TIME t;
        int db_fd;
-
-       /* If we already have an open database, close it. */
-       if (db_file) {
-               fclose (db_file);
-               db_file = (FILE *)0;
-       }
+       FILE *new_db_file;
 
        /* Make a temporary lease file... */
        GET_TIME (&t);
@@ -873,11 +876,17 @@ int new_lease_file ()
                log_error ("Can't create new lease file: %m");
                return 0;
        }
-       if ((db_file = fdopen (db_fd, "w")) == NULL) {
-               log_error ("Can't fdopen new lease file!");
-               goto fail;
+       if ((new_db_file = fdopen(db_fd, "w")) == NULL) {
+               log_error("Can't fdopen new lease file: %m");
+               close(db_fd);
+               goto fdfail;
        }
 
+       /* Close previous database, if any. */
+       if (db_file)
+               fclose(db_file);
+       db_file = new_db_file;
+
        /* Write an introduction so people don't complain about time
           being off. */
        errno = 0;
@@ -933,10 +942,15 @@ int new_lease_file ()
                           backfname);
                goto fail;
            }
-           if (link (path_dhcpd_db, backfname) < 0) {
-               log_error ("Can't backup lease database %s to %s: %m",
-                          path_dhcpd_db, backfname);
-               goto fail;
+           if (link(path_dhcpd_db, backfname) < 0) {
+               if (errno == ENOENT) {
+                       log_error("%s is missing - no lease db to backup.",
+                                 path_dhcpd_db);
+               } else {
+                       log_error("Can't backup lease database %s to %s: %m",
+                                 path_dhcpd_db, backfname);
+                       goto fail;
+               }
            }
 #if defined (TRACING)
        }
@@ -954,8 +968,9 @@ int new_lease_file ()
        return 1;
 
       fail:
-       unlink (newfname);
        lease_file_is_corrupt = 1;
+      fdfail:
+       unlink (newfname);
        return 0;
 }
 
index 3cc266cf42d78cb9e2b02b3144ac9d806e817986..8eb7524bbc746c013dbad5c264f994a3e50f5b95 100644 (file)
@@ -3,7 +3,7 @@
    DHCP Protocol engine. */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dhcp.c,v 1.199 2005/09/30 19:15:55 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhcp.c,v 1.200 2006/02/24 23:16:30 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -188,17 +188,16 @@ void dhcp (packet)
        }
       nolease:
 
-       /* Classify the client. */
+       /* If a client null terminates options it sends, it probably
+        * expects the server to reciprocate.
+        */
        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                                 DHO_HOST_NAME))) {
                if (!oc -> expression)
-                       while (oc -> data.len &&
-                              oc -> data.data [oc -> data.len - 1] == 0) {
-                               ms_nulltp = 1;
-                               oc -> data.len--;
-                       }
+                       ms_nulltp = oc->flags & OPTION_HAD_NULLS;
        }
 
+       /* Classify the client. */
        classify_client (packet);
 
        switch (packet -> packet_type) {
@@ -245,15 +244,13 @@ void dhcpdiscover (packet, ms_nulltp)
        char msgbuf [1024]; /* XXX */
        TIME when;
        const char *s;
-       int allocatedp = 0;
        int peer_has_leases = 0;
-       int alloc_lease_called = 0;
 #if defined (FAILOVER_PROTOCOL)
        dhcp_failover_state_t *peer;
 #endif
 
        find_lease (&lease, packet, packet -> shared_network,
-                   0, &allocatedp, (struct lease *)0, MDL);
+                   0, &peer_has_leases, (struct lease *)0, MDL);
 
        if (lease && lease -> client_hostname) {
                if ((strlen (lease -> client_hostname) <= 64) &&
@@ -292,22 +289,20 @@ void dhcpdiscover (packet, ms_nulltp)
        if (lease && lease -> pool && lease -> pool -> failover_peer) {
                peer = lease -> pool -> failover_peer;
 
-               /* If the lease is ours to allocate, then allocate it,
-                  but set the allocatedp flag. */
-               if (lease_mine_to_reallocate (lease))
-                       allocatedp = 1;
+               /* If the lease is ours to allocate, then allocate it. */
+               if (lease_mine_to_reallocate(lease)) {
+                       if (lease->pool && lease->pool->failover_peer)
+                               dhcp_failover_pool_check(lease->pool);
 
-               /* If the lease is active, do load balancing to see who
-                  allocates the lease (if it's active, it already belongs
-                  to the client, or we wouldn't have gotten it from
-                  find_lease (). */
-               else if (lease -> binding_state == FTS_ACTIVE &&
-                        (peer -> service_state != cooperating ||
-                         load_balance_mine (packet, peer)))
-                       ;
+               /* If the lease is active, it belongs to the client.  This
+                * is the right lease, if we are to offer one.  We decide
+                * wether or not to offer later on.
+                */
+               } else if (lease->binding_state == FTS_ACTIVE) {
+                       ; /* This space intentionally left blank. */
 
                /* Otherwise, we can't let the client have this lease. */
-               else {
+               else {
 #if defined (DEBUG_FIND_LEASE)
                    log_debug ("discarding %s - %s",
                               piaddr (lease -> ip_addr),
@@ -336,8 +331,6 @@ void dhcpdiscover (packet, ms_nulltp)
                if (lease -> pool && lease -> pool -> failover_peer)
                        dhcp_failover_pool_check (lease -> pool);
 #endif
-               allocatedp = 1;
-               alloc_lease_called = 1;
        }
 
 #if defined (FAILOVER_PROTOCOL)
@@ -353,26 +346,15 @@ void dhcpdiscover (packet, ms_nulltp)
                peer = (dhcp_failover_state_t *)0;
 
        /* Do load balancing if configured. */
-       /* If the lease is newly allocated, and we're not the server that
-          the client would normally get with load balancing, and the
-          failover protocol state is normal, let the other server get this.
-          XXX Check protocol spec to make sure that predicating this on
-          XXX allocatedp is okay - I'm doing this so that the client won't
-          XXX be forced to switch servers (and IP addresses) just because
-          XXX of bad luck, when it's possible for it to get the address it
-          XXX is requesting.    Not sure this is allowed.  */
-       if (allocatedp && peer && (peer -> service_state == cooperating) &&
+       if (peer && (peer -> service_state == cooperating) &&
            !load_balance_mine (packet, peer)) {
-               /* peer_has_leases only has a chance to be set if we called
-                * allocate_lease() above.
-                */
-               if (!alloc_lease_called || peer_has_leases) {
+               if (peer_has_leases) {
                        log_debug ("%s: load balance to peer %s",
                                   msgbuf, peer -> name);
                        goto out;
                } else {
-                       log_debug ("cancel load balance to peer %s - %s",
-                                  peer -> name, "no free leases");
+                       log_debug ("%s: cancel load balance to peer %s - %s",
+                                  msgbuf, peer -> name, "no free leases");
                }
        }
 #endif
@@ -442,8 +424,6 @@ void dhcprequest (packet, ms_nulltp, ip_lease)
        if (find_subnet (&subnet, cip, MDL))
                find_lease (&lease, packet,
                            subnet -> shared_network, &ours, 0, ip_lease, MDL);
-       /* XXX consider using allocatedp arg to find_lease to see
-          XXX that this isn't a compliant DHCPREQUEST. */
 
        if (lease && lease -> client_hostname) {
                if ((strlen (lease -> client_hostname) <= 64) &&
@@ -953,7 +933,7 @@ void dhcpinform (packet, ms_nulltp)
        struct packet outgoing;
        unsigned char dhcpack = DHCPACK;
        struct subnet *subnet = (struct subnet *)0;
-       struct iaddr cip;
+       struct iaddr cip, gip;
        unsigned i, j;
        int nulltp;
        struct sockaddr_in to;
@@ -970,11 +950,19 @@ void dhcpinform (packet, ms_nulltp)
                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
        }
 
+       if (packet->raw->giaddr.s_addr) {
+               gip.len = 4;
+               memcpy(gip.iabuf, &packet->raw->giaddr, 4);
+       } else
+               gip.len = 0;
+
        /* %Audit% This is log output. %2004.06.17,Safe%
         * If we truncate we hope the user can get a hint from the log.
         */
        snprintf (msgbuf, sizeof msgbuf, "DHCPINFORM from %s via %s",
-                piaddr (cip), packet -> interface -> name);
+                piaddr (cip), packet->raw->giaddr.s_addr ?
+                               inet_ntoa(packet->raw->giaddr) :
+                               packet -> interface -> name);
 
        /* If the IP source address is zero, don't respond. */
        if (!memcmp (cip.iabuf, "\0\0\0", 4)) {
@@ -983,13 +971,18 @@ void dhcpinform (packet, ms_nulltp)
        }
 
        /* Find the subnet that the client is on. */
-       oc = (struct option_cache *)0;
-       find_subnet (&subnet , cip, MDL);
+       if (gip.len) {
+               /* XXX - do subnet selection relay agent suboption here */
+               find_subnet(&subnet, gip, MDL);
+       } else {
+               /* XXX - do subnet selection (not relay agent) option here */
+               find_subnet(&subnet, cip, MDL);
+       }
 
        /* Sourceless packets don't make sense here. */
        if (!subnet) {
-               log_info ("%s: unknown subnet %s",
-                         msgbuf, inet_ntoa (packet -> raw -> giaddr));
+               log_info ("%s: unknown subnet for address %s",
+                         msgbuf, gip.len ? piaddr(gip) : piaddr(cip));
                return;
        }
 
@@ -1018,7 +1011,6 @@ void dhcpinform (packet, ms_nulltp)
                return;
        }
 
-       memset (&d1, 0, sizeof d1);
        option_state_allocate (&options, MDL);
        memset (&outgoing, 0, sizeof outgoing);
        memset (&raw, 0, sizeof raw);
@@ -1080,14 +1072,8 @@ void dhcpinform (packet, ms_nulltp)
        nulltp = 0;
        if ((oc = lookup_option (&dhcp_universe, packet -> options,
                                 DHO_HOST_NAME))) {
-               if (evaluate_option_cache (&d1, packet, (struct lease *)0,
-                                          (struct client_state *)0,
-                                          packet -> options, options,
-                                          &global_scope, oc, MDL)) {
-                       if (d1.data [d1.len - 1] == '\0')
-                               nulltp = 1;
-                       data_string_forget (&d1, MDL);
-               }
+               if (!oc->expression)
+                       nulltp = oc->flags & OPTION_HAD_NULLS;
        }
 
        /* Put in DHCP-specific options. */
@@ -1250,9 +1236,6 @@ void dhcpinform (packet, ms_nulltp)
        raw.hops = packet -> raw -> hops;
        raw.op = BOOTREPLY;
 
-       /* Report what we're sending... */
-       log_info ("DHCPACK to %s", inet_ntoa (raw.ciaddr));
-
 #ifdef DEBUG_PACKET
        dump_packet (&outgoing);
        dump_raw ((unsigned char *)&raw, outgoing.packet_length);
@@ -1265,9 +1248,47 @@ void dhcpinform (packet, ms_nulltp)
 #endif
        memset (to.sin_zero, 0, sizeof to.sin_zero);
 
-       /* Use the IP address we derived for the client. */
-       memcpy (&to.sin_addr, cip.iabuf, 4);
-       to.sin_port = remote_port;
+       /* RFC2131 states the server SHOULD unciast to ciaddr.
+        * There are two wrinkles - relays, and when ciaddr is zero.
+        * There's actually no mention of relays at all in rfc2131.
+        * I think it's best to use relays where present...a relay is
+        * a bit more trustworthy about getting the message to a client
+        * than a client might be (it's better to send to a relay than
+        * to, say, a link-local address the client has selected).
+        *
+        * Where ciaddr is zero, which actually does happen quite frequently
+        * even though rfc2131 is unequivocal on the subject, we try to help
+        * by using the IP source address.
+        *
+        * Where ciaddr is zero AND we got it via a relay, the IP source
+        * address is the relay - and we're transmitting to the client
+        * port.  This might cause a loop.
+        *
+        * So, overall, this is neater if the relay is selected first,
+        * treated like a relay, client addressing taken second.  Since
+        * a relay possibly has no way of knowing how to reach the client
+        * if chaddr is zero (equally as common as ciaddr being zeroed),
+        * set the broadcast bit to try and help.
+        */
+       if (gip.len) {
+               memcpy(&to.sin_addr, gip.iabuf, 4);
+               to.sin_port = local_port;
+
+               if (!raw.hlen)
+                       raw.flags |= htons(BOOTP_BROADCAST);
+       } else {
+               memcpy(&to.sin_addr, cip.iabuf, 4);
+               to.sin_port = remote_port;
+       }
+
+       /* Report what we're sending. */
+       snprintf(msgbuf, sizeof msgbuf, "DHCPACK to %s (%s) via", piaddr(cip),
+                (packet->raw->htype && packet->raw->hlen) ?
+                       print_hw_addr(packet->raw->htype, packet->raw->hlen,
+                                     packet->raw->chaddr) :
+                       "<no client hardware address>");
+       log_info("%s %s", msgbuf, gip.len ? piaddr(gip) :
+                                           packet->interface->name);
 
        errno = 0;
        send_packet ((fallback_interface
@@ -2011,57 +2032,57 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
 #if defined (FAILOVER_PROTOCOL)
                /* Okay, we know the lease duration.   Now check the
                   failover state, if any. */
-               if (lease -> tsfp) {
-                       lt ->tsfp = lease ->tsfp;
-               }
                if (lease -> pool && lease -> pool -> failover_peer) {
+                       TIME new_lease_time = lease_time;
                        dhcp_failover_state_t *peer =
                            lease -> pool -> failover_peer;
 
-                       /* If the lease time we arrived at exceeds what
-                          the peer has, we can only issue a lease of
-                          peer -> mclt, but we can tell the peer we
-                          want something longer in the future. */
-                       /* XXX This may result in updates that only push
-                          XXX the peer's expiry time for this lease up
-                          XXX by a few seconds - think about this again
-                          XXX later. */
-                       if (lease_time > peer -> mclt &&
-                           cur_time + lease_time > lease -> tsfp) {
-                               /* Here we're assuming that if we don't have
-                                  to update tstp, there's already an update
-                                  queued.   May want to revisit this.  */
-                               if (peer -> me.state != partner_down &&
-                                   cur_time + lease_time > lease -> tstp)
-                                       lt -> tstp = (cur_time + lease_time +
-                                                     peer -> mclt / 2);
-
-                               /* Now choose a lease time that is either
-                                  MCLT, for a lease that's never before been
-                                  assigned, or TSFP + MCLT for a lease that
-                                  has.
-                                  XXX Note that TSFP may be < cur_time.
-                                  XXX What do we do in this case?
-                                  XXX should the expiry timer on the lease
-                                  XXX set tsfp and tstp to zero? */
-                               if (lease -> tsfp < cur_time) {
-                                       lease_time = peer -> mclt;
-                               } else {
-                                       lease_time = (lease -> tsfp  - cur_time
-                                                     + peer -> mclt);
-                               }
-                       } else {
-                               if (cur_time + lease_time > lease -> tsfp &&
-                                   lease_time > peer -> mclt / 2) {
-                                       lt -> tstp = (cur_time + lease_time +
-                                                     peer -> mclt / 2);
-                               } else { 
-                                       lt -> tstp = (cur_time + lease_time +
-                                                     lease_time / 2);
-                               }
+                       /* Copy previous lease failover ack-state. */
+                       lt->tsfp = lease->tsfp;
+                       lt->atsfp = lease->atsfp;
+
+                       /* Update Client Last Transaction Time. */
+                       lt->cltt = cur_time;
+
+                       /* Lease times less than MCLT are not a concern. */
+                       if (lease_time > peer->mclt) {
+                               /* Each server can only offer a lease time
+                                * that is either equal to MCLT (at least),
+                                * or up to TSFP+MCLT.  Only if the desired
+                                * lease time falls within TSFP+MCLT, can
+                                * the server allow it.
+                                */
+                               if (lt->tsfp <= cur_time)
+                                       new_lease_time = peer->mclt;
+                               else if ((cur_time + lease_time) >
+                                        (lt->tsfp + peer->mclt))
+                                       new_lease_time = (lt->tsfp - cur_time)
+                                                               + peer->mclt;
                        }
 
-                       lt -> cltt = cur_time;
+                       /* Update potential expiry.  Allow for the desired
+                        * lease time plus one half the actual (wether
+                        * modified downward or not) lease time, which is
+                        * actually an estimate of when the client will
+                        * renew.  This way, the client will be able to get
+                        * the desired lease time upon renewal.
+                        */
+                       if (offer == DHCPACK) {
+                               lt->tstp = cur_time + lease_time +
+                                               (new_lease_time / 2);
+
+                               /* If we reduced the potential expiry time,
+                                * make sure we don't offer an old-expiry-time
+                                * lease for this lease before the change is
+                                * ack'd.
+                                */
+                               if (lt->tstp < lt->tsfp)
+                                       lt->tsfp = lt->tstp;
+                       } else
+                               lt->tstp = lease->tstp;
+
+                       /* Use failover-modified lease time.  */
+                       lease_time = new_lease_time;
                }
 #endif /* FAILOVER_PROTOCOL */
 
@@ -2933,7 +2954,7 @@ void dhcp_reply (lease)
 
 int find_lease (struct lease **lp,
                struct packet *packet, struct shared_network *share, int *ours,
-               int *allocatedp, struct lease *ip_lease_in,
+               int *peer_has_leases, struct lease *ip_lease_in,
                const char *file, int line)
 {
        struct lease *uid_lease = (struct lease *)0;
@@ -2952,6 +2973,22 @@ int find_lease (struct lease **lp,
        int status;
        struct hardware h;
 
+       /* Quick check to see if the peer has leases. */
+       if (peer_has_leases) {
+               struct pool *pool;
+
+               for (pool = share->pools ; pool ; pool = pool->next) {
+                       dhcp_failover_state_t *peer = pool->failover_peer;
+
+                       if (peer &&
+                           ((peer->i_am == primary && pool->backup_leases) ||
+                            (peer->i_am == secondary && pool->free_leases))) {
+                               *peer_has_leases = 1;
+                               break;
+                       }
+               }
+       }
+
        if (packet -> raw -> ciaddr.s_addr) {
                cip.len = 4;
                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
@@ -3257,9 +3294,7 @@ int find_lease (struct lease **lp,
                        if (ours && ip_lease -> binding_state != FTS_ACTIVE)
                                *ours = 0;
                        lease_dereference (&ip_lease, MDL);
-               } else
-                       if (allocatedp)
-                               *allocatedp = 1;
+               }
        }
 
        /* If we got an ip_lease and a uid_lease or hw_lease, and ip_lease
@@ -3310,7 +3345,7 @@ int find_lease (struct lease **lp,
                                    (share ==
                                     uid_lease -> subnet -> shared_network) &&
                                    packet -> packet_type == DHCPREQUEST)
-                                       dissociate_lease (uid_lease);
+                                       release_lease (uid_lease, packet);
                            }
                            lease_dereference (&uid_lease, MDL);
                            lease_reference (&uid_lease, ip_lease, MDL);
@@ -3380,8 +3415,10 @@ int find_lease (struct lease **lp,
              permitted (packet, ip_lease -> pool -> prohibit_list)) ||
             (ip_lease -> pool -> permit_list &&
              !permitted (packet, ip_lease -> pool -> permit_list)))) {
-               if (!packet -> raw -> ciaddr.s_addr)
+               if (!packet->raw->ciaddr.s_addr &&
+                   (ip_lease->binding_state == FTS_ACTIVE))
                        release_lease (ip_lease, packet);
+
                lease_dereference (&ip_lease, MDL);
        }
 
@@ -3458,11 +3495,19 @@ int find_lease (struct lease **lp,
           the lease that matched the client identifier. */
        if (uid_lease) {
                if (lease) {
+                       log_error("uid lease %s for client %s is duplicate "
+                                 "on %s",
+                                 piaddr(uid_lease->ip_addr),
+                                 print_hw_addr(packet->raw->htype,
+                                               packet->raw->hlen,
+                                               packet->raw->chaddr),
+                                 uid_lease->subnet->shared_network->name);
+
                        if (!packet -> raw -> ciaddr.s_addr &&
                            packet -> packet_type == DHCPREQUEST &&
                            (uid_lease -> binding_state == FTS_ACTIVE ||
                             uid_lease -> binding_state == FTS_BOOTP))
-                               dissociate_lease (uid_lease);
+                               release_lease(uid_lease, packet);
 #if defined (DEBUG_FIND_LEASE)
                        log_info ("not choosing uid lease.");
 #endif
@@ -3556,9 +3601,6 @@ int find_lease (struct lease **lp,
                lease_dereference (&lease, MDL);
        }
 
-       if (lease && allocatedp && lease -> ends <= cur_time)
-               *allocatedp = 1;
-
       out:
        if (have_client_identifier)
                data_string_forget (&client_identifier, MDL);
index 9b9fdc842c8f9dcd2813a622bbced340cbc0e8f9..11be0532be1f49d3e235cdee2c173222a3f718d0 100644 (file)
@@ -1,6 +1,6 @@
 .\"    dhcpd.8
 .\"
-.\" Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
@@ -28,7 +28,7 @@
 .\" see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 .\" ``http://www.nominum.com''.
 .\"
-.\" $Id: dhcpd.8,v 1.22 2005/03/17 20:15:27 dhankins Exp $
+.\" $Id: dhcpd.8,v 1.23 2006/02/24 23:16:31 dhankins Exp $
 .\"
 .TH dhcpd 8
 .SH NAME
@@ -62,6 +62,10 @@ dhcpd - Dynamic Host Configuration Protocol Server
 .I lease-file
 ]
 [
+.B -pf
+.I pid-file
+]
+[
 .B -tf
 .I trace-output-file
 ]
@@ -193,8 +197,10 @@ LOG_DAEMON.
 .PP
 Dhcpd can be made to use an alternate configuration file with the
 .B -cf
-flag, or an alternate lease file with the
+flag, an alternate lease file with the
 .B -lf
+flag, or an alternate pid file with the
+.B -pf
 flag.   Because of the importance of using the same lease database at
 all times when running dhcpd in production, these options should be
 used \fBonly\fR for testing lease files or database files in a
@@ -463,9 +469,16 @@ server.
 .RE
 .B tsfp \fItime\fR examine
 .RS 0.5i
-the time when the lease's current state ends, as understood by the
-failover peer (if there is no failover peer, this value is
-undefined).
+the adjusted time when the lease's current state ends, as understood by
+the failover peer (if there is no failover peer, this value is
+undefined).  Generally this value is only adjusted for expired, released,
+or reset leases while the server is operating in partner-down state, and
+otherwise is simply the value supplied by the peer.
+.RE
+.B atsfp \fItime\fR examine
+.RS 0.5i
+the actual tsfp value sent from the peer.  This value is forgotten when a
+lease binding state change is made, to facillitate retransmission logic.
 .RE
 .PP
 .B cltt \fItime\fR examine
index a50a6ff2977650b7b1a58672119e6c6508f18531..5a91d8610f59fa3392951f50d9247c6b9769e897 100644 (file)
@@ -1,6 +1,6 @@
 .\"    dhcpd.conf.5
 .\"
-.\" Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
@@ -28,7 +28,7 @@
 .\" see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 .\" ``http://www.nominum.com''.
 .\"
-.\" $Id: dhcpd.conf.5,v 1.69 2005/09/30 19:15:55 dhankins Exp $
+.\" $Id: dhcpd.conf.5,v 1.70 2006/02/24 23:16:31 dhankins Exp $
 .\"
 .TH dhcpd.conf 5
 .SH NAME
@@ -2108,9 +2108,7 @@ statement
 The \fInext-server\fR statement is used to specify the host address of
 the server from which the initial boot file (specified in the
 \fIfilename\fR statement) is to be loaded.   \fIServer-name\fR should
-be a numeric IP address or a domain name.   If no \fInext-server\fR
-parameter applies to a given client, the DHCP server's IP address is
-used.
+be a numeric IP address or a domain name.
 .RE
 .PP
 The
index c7b31936af15a47301340f8eb794ee6dc5749eed..cc42d5d5b9a02e683c5d0e6d958fbb203b651a72 100644 (file)
@@ -3,7 +3,7 @@
    Failover protocol support code... */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: failover.c,v 1.58 2005/03/17 20:15:28 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: failover.c,v 1.59 2006/02/24 23:16:32 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1780,23 +1780,26 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state,
 
          case partner_down:
            /* For every expired lease, set a timeout for it to become free. */
-            for (s = shared_networks; s; s = s -> next) {
-                for (p = s -> pools; p; p = p -> next) {
+           for (s = shared_networks; s; s = s -> next) {
+               for (p = s -> pools; p; p = p -> next) {
                    if (p -> failover_peer == state) {
-                       for (l = p -> expired; l; l = l -> next)
-                           l -> tsfp = state -> me.stos + state -> mclt;
-                       if (p -> next_event_time >
-                           state -> me.stos + state -> mclt) {
-                           p -> next_event_time =
-                                       state -> me.stos + state -> mclt;
+                       for (l = p->expired ; l ; l = l->next) {
+                           l->tsfp = state->me.stos + state->mclt;
+                           l->sort_time = (l->tsfp > l->ends) ?
+                                          l->tsfp : l->ends;
+                       }
+                       if (p->expired &&
+                           (p->expired->sort_time < p->next_event_time)) {
+
+                           p->next_event_time = p->expired->sort_time;
 #if defined (DEBUG_FAILOVER_TIMING)
                            log_info ("add_timeout +%d %s",
-                                     (int)(cur_time - p -> next_event_time),
+                                     (int)(cur_time - p->next_event_time),
                                      "pool_timer");
 #endif
-                           add_timeout (p -> next_event_time, pool_timer, p,
-                                        (tvref_t)pool_reference,
-                                                (tvunref_t)pool_dereference);
+                           add_timeout(p->next_event_time, pool_timer, p,
+                                       (tvref_t)pool_reference,
+                                       (tvunref_t)pool_dereference);
                        }
                    }
                }
@@ -4496,7 +4499,7 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
                        goto bad;
                }
                if (msg -> chaddr.count > sizeof lt -> hardware_addr.hbuf) {
-                       message = "chaddr to long";
+                       message = "chaddr too long";
                        goto bad;
                }
                lt -> hardware_addr.hlen = msg -> chaddr.count;
@@ -4571,8 +4574,8 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
        if (msg -> options_present & FTB_CLTT) {
                lt -> cltt = msg -> client_ltt;
        }
-       if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
-               lt -> tsfp = msg -> potential_expiry;
+       if (msg->options_present & FTB_POTENTIAL_EXPIRY) {
+               lt->atsfp = lt->tsfp = msg->potential_expiry;
        }
 
        if (msg -> options_present & FTB_BINDING_STATUS) {
@@ -4680,20 +4683,20 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
        if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
                /* XXX it could be a problem to do this directly if the
                   XXX lease is sorted by tsfp. */
+               lease->atsfp = lease->tsfp = msg->potential_expiry;
+
                if ((lease -> binding_state == FTS_EXPIRED ||
                     lease -> binding_state == FTS_RESET ||
                     lease -> binding_state == FTS_RELEASED) &&
                    (msg -> options_present & FTB_BINDING_STATUS) &&
                    msg -> binding_status == FTS_FREE)
                {
-                       lease -> tsfp = msg -> potential_expiry;
                        lease -> next_binding_state = FTS_FREE;
                        supersede_lease (lease, (struct lease *)0, 0, 0, 0);
                        write_lease (lease);
                        if (state -> me.state == normal)
                                commit_leases ();
                } else {
-                       lease -> tsfp = msg -> potential_expiry;
                        if ((lease -> desired_binding_state !=
                             lease -> binding_state) &&
                            (msg -> options_present & FTB_BINDING_STATUS) &&
@@ -4811,6 +4814,9 @@ isc_result_t dhcp_failover_generate_update_queue (dhcp_failover_state_t *state,
           expiry routine on the pool. */
        for (s = shared_networks; s; s = s -> next) {
            for (p = s -> pools; p; p = p -> next) {
+               if (p->failover_peer != state)
+                       continue;
+
                lptr [FREE_LEASES] = &p -> free;
                lptr [ACTIVE_LEASES] = &p -> active;
                lptr [EXPIRED_LEASES] = &p -> expired;
@@ -4819,11 +4825,11 @@ isc_result_t dhcp_failover_generate_update_queue (dhcp_failover_state_t *state,
 
                for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
                    for (l = *(lptr [i]); l; l = l -> next) {
-                       if (p -> failover_peer == state &&
-                           ((everythingp &&
-                             (l -> starts != MIN_TIME ||
-                              l -> ends != MIN_TIME)) ||
-                            l -> tstp > l -> tsfp)) {
+                       if ((everythingp &&
+                            (l->starts != MIN_TIME ||
+                             l->ends != MIN_TIME)) ||
+                           (l->tstp > l->atsfp) ||
+                           (i == EXPIRED_LEASES)) {
                                l -> desired_binding_state = l -> binding_state;
                                dhcp_failover_queue_update (l, 0);
                        }
@@ -5281,21 +5287,29 @@ conflict_binding_state_transition_check (struct lease *lease,
                        switch (binding_state) {
                              case FTS_FREE:
                              case FTS_BACKUP:
-                             case FTS_ABANDONED:
                                new_state = lease -> binding_state;
                                break;
 
                              case FTS_EXPIRED:
-                             case FTS_RELEASED:
-                             case FTS_RESET:
-                               if (lease -> ends > cur_time)
-                                       new_state =
-                                               lease -> binding_state;
+                               /* If we don't agree about expiry, it's
+                                * invalid.  65 should allow for max
+                                * clock skew (60) plus some fudge.
+                                * XXX: should we refetch cur_time?
+                                */
+                               if ((lease->ends - 65) > cur_time)
+                                       new_state = lease->binding_state;
                                else
                                        new_state = binding_state;
                                break;
 
-                             case FTS_ACTIVE:
+                               /* RELEASED, RESET, and ABANDONED indicate
+                                * that our partner has information about
+                                * this lease that we did not witness.  Our
+                                * partner wins.
+                                */
+                             case FTS_RELEASED:
+                             case FTS_RESET:
+                             case FTS_ABANDONED:
                                new_state = binding_state;
                                break;
 
@@ -5333,48 +5347,77 @@ int lease_mine_to_reallocate (struct lease *lease)
 {
        dhcp_failover_state_t *peer;
 
-       if (lease && lease -> pool &&
-           lease -> pool -> failover_peer) {
-               peer = lease -> pool -> failover_peer;
-               switch (lease -> binding_state) {
+       if (lease && lease->pool &&
+           (peer = lease->pool->failover_peer)) {
+               switch (lease->binding_state) {
                      case FTS_ACTIVE:
+                       /* ACTIVE leases may not be reallocated. */
                        return 0;
 
                      case FTS_FREE:
+                     case FTS_ABANDONED:
+                       /* FREE leases may only be allocated by the primary,
+                        * unless the secondary is acting in partner_down
+                        * state and stos+mclt or tsfp+mclt has expired,
+                        * whichever is greater.
+                        *
+                        * ABANDONED are treated the same as FREE for all
+                        * purposes here.  Note that servers will only try
+                        * for ABANDONED leases as a last resort anyway.
+                        */
                        if (peer -> i_am == primary)
                                return 1;
-                       if (peer -> service_state == service_partner_down &&
-                           (lease -> tsfp < peer -> me.stos
-                            ? peer -> me.stos + peer -> mclt < cur_time
-                            : lease -> tsfp + peer -> mclt < cur_time))
-                               return 1;
-                       return 0;
 
-                     case FTS_ABANDONED:
+                       return(peer->service_state == service_partner_down &&
+                              ((lease->tsfp < peer->me.stos) ?
+                               (peer->me.stos + peer->mclt < cur_time) :
+                               (lease->tsfp + peer->mclt < cur_time)));
+
                      case FTS_RESET:
                      case FTS_RELEASED:
                      case FTS_EXPIRED:
-                       if (peer -> service_state == service_partner_down &&
-                           (lease -> tsfp < peer -> me.stos
-                            ? peer -> me.stos + peer -> mclt < cur_time
-                            : lease -> tsfp + peer -> mclt < cur_time))
-                               return 1;
-                       return 0;
+                       /* These three lease states go onto the 'expired'
+                        * queue.  Upon entry into partner-down state, this
+                        * queue of leases has their tsfp values modified
+                        * to equal stos+mclt, the point at which the server
+                        * is allowed to remove them from these transitional
+                        * states without an acknowledgement.
+                        *
+                        * Note that although tsfp has been possibly extended
+                        * past the actual tsfp we received from the peer, we
+                        * don't have to take any special action.  Since tsfp
+                        * is now in the past (or now), we can guarantee that
+                        * this server will only allocate a lease time equal
+                        * to MCLT, rather than a TSFP-optimal lease, which is
+                        * the only danger for a lease in one of these states.
+                        */
+                       return((peer->service_state == service_partner_down) &&
+                              (lease->tsfp < cur_time));
+
                      case FTS_BACKUP:
-                       if (peer -> i_am == secondary)
-                               return 1;
-                       if (peer -> service_state == service_partner_down &&
-                           (lease -> tsfp < peer -> me.stos
-                            ? peer -> me.stos + peer -> mclt < cur_time
-                            : lease -> tsfp + peer -> mclt < cur_time))
+                       /* Only the secondary may allocate BACKUP leases,
+                        * unless in partner_down state in which case at
+                        * least TSFP+MCLT or STOS+MCLT must have expired,
+                        * whichever is greater.
+                        */
+                       if (peer->i_am == secondary)
                                return 1;
-                       return 0;
+
+                       return((peer->service_state == service_partner_down) &&
+                              ((lease->tsfp < peer->me.stos) ?
+                               (peer->me.stos + peer->mclt < cur_time) :
+                               (lease->tsfp + peer->mclt < cur_time)));
+
+                     default:
+                       /* All lease states appear above. */
+                       log_fatal("Impossible case at %s:%d.", MDL);
+                       break;
                }
                return 0;
        }
        if (lease)
-               return !(lease -> binding_state != FTS_FREE &&
-                        lease -> binding_state != FTS_BACKUP);
+               return(lease->binding_state == FTS_FREE ||
+                      lease->binding_state == FTS_BACKUP);
        else
                return 0;
 }
index 52e09fff91b0311d3f7de55d2cb0bde2c116835b..c7768c1a40df9471ca704288aa1ceb1c3b82f053 100644 (file)
@@ -3,7 +3,7 @@
    Server-specific in-memory database support. */
 
 /*
- * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: mdb.c,v 1.73 2005/09/30 17:57:32 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: mdb.c,v 1.74 2006/02/24 23:16:32 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -921,7 +921,7 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
                comp -> uid = (unsigned char *)0;
        } else
                enter_uid = 1;
-       
+
        if (comp -> hardware_addr.hlen &&
            ((comp -> hardware_addr.hlen !=
              lease -> hardware_addr.hlen) ||
@@ -932,7 +932,7 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
                enter_hwaddr = 1;
        } else if (!comp -> hardware_addr.hlen)
                enter_hwaddr = 1;
-       
+
        /* If the lease has been billed to a class, remove the billing. */
        if (comp -> billing_class != lease -> billing_class) {
                if (comp -> billing_class)
@@ -1019,26 +1019,36 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
                executable_statement_reference (&comp -> on_release,
                                                lease -> on_release, MDL);
        }
-       
+
        /* Record the lease in the uid hash if necessary. */
        if (enter_uid && comp -> uid) {
                uid_hash_add (comp);
        }
-       
+
        /* Record it in the hardware address hash if necessary. */
        if (enter_hwaddr && lease -> hardware_addr.hlen) {
                hw_hash_add (comp);
        }
-       
+
 #if defined (FAILOVER_PROTOCOL)
-       comp -> cltt = lease -> cltt;
-       comp -> tstp = lease -> tstp;
-       comp -> tsfp = lease -> tsfp;
+       comp->cltt = lease->cltt;
+       comp->tstp = lease->tstp;
+       comp->tsfp = lease->tsfp;
+       comp->atsfp = lease->atsfp;
 #endif /* FAILOVER_PROTOCOL */
-       comp -> ends = lease -> ends;
-       comp -> next_binding_state = lease -> next_binding_state;
+       comp->ends = lease->ends;
+       comp->next_binding_state = lease->next_binding_state;
 
       just_move_it:
+#if defined (FAILOVER_PROTOCOL)
+       /* Atsfp should be cleared upon any state change that implies
+        * propogation wether supersede_lease was given a copy lease
+        * structure or not (often from the pool_timer()).
+        */
+       if (propogate)
+               comp->atsfp = 0;
+#endif /* FAILOVER_PROTOCOL */
+
        if (!comp -> pool) {
                log_error ("Supersede_lease: lease %s with no pool.",
                           piaddr (comp -> ip_addr));
@@ -1082,6 +1092,7 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
 
        /* Remove the lease from its current place in its current
           timer sequence. */
+       /* XXX this is horrid. */
        prev = (struct lease *)0;
        for (lp = *lq; lp; lp = lp -> next) {
                if (lp == comp)
@@ -1398,14 +1409,15 @@ int lease_copy (struct lease **lp,
                executable_statement_reference (&lt -> on_release,
                                                lease -> on_release,
                                                file, line);
-       lt -> flags = lease -> flags;
-       lt -> tstp = lease -> tstp;
-       lt -> tsfp = lease -> tsfp;
-       lt -> cltt = lease -> cltt;
-       lt -> binding_state = lease -> binding_state;
-       lt -> next_binding_state = lease -> next_binding_state;
-       status = lease_reference (lp, lt, file, line);
-       lease_dereference (&lt, MDL);
+       lt->flags = lease->flags;
+       lt->tstp = lease->tstp;
+       lt->tsfp = lease->tsfp;
+       lt->atsfp = lease->atsfp;
+       lt->cltt = lease -> cltt;
+       lt->binding_state = lease->binding_state;
+       lt->next_binding_state = lease->next_binding_state;
+       status = lease_reference(lp, lt, file, line);
+       lease_dereference(&lt, MDL);
        return status == ISC_R_SUCCESS;
 }
 
@@ -1924,6 +1936,18 @@ int write_leases ()
        return 1;
 }
 
+/* In addition to placing this lease upon a lease queue depending on its
+ * state, it also keeps track of the number of FREE and BACKUP leases in
+ * existence, and sets the sort_time on the lease.
+ *
+ * Sort_time is used in pool_timer() to determine when the lease will
+ * bubble to the top of the list and be supersede_lease()'d into its next
+ * state (possibly, if all goes well).  Example, ACTIVE leases move to
+ * EXPIRED state when the 'ends' value is reached, so that is its sort
+ * time.  Most queues are sorted by 'ends', since it is generally best
+ * practice to re-use the oldest lease, to reduce address collision
+ * chances.
+ */
 int lease_enqueue (struct lease *comp)
 {
        struct lease **lq, *prev, *lp;
@@ -1949,7 +1973,26 @@ int lease_enqueue (struct lease *comp)
              case FTS_RELEASED:
              case FTS_RESET:
                lq = &comp -> pool -> expired;
-               comp -> sort_time = comp -> ends;
+#if defined(FAILOVER_PROTOCOL)
+               /* In partner_down, tsfp is the time at which the lease
+                * may be reallocated (stos+mclt).  We can do that with
+                * lease_mine_to_reallocate() anywhere between tsfp and
+                * ends.  But we prefer to wait until ends before doing it
+                * automatically (choose the greater of the two).  Note
+                * that 'ends' is usually a historic timestamp in the
+                * case of expired leases, is really only in the future
+                * on released leases, and if we know a lease to be released
+                * the peer might still know it to be active...in which case
+                * it's possible the peer has renewed this lease, so avoid
+                * doing that.
+                */
+               if (comp->pool->failover_peer &&
+                   comp->pool->failover_peer->me.state == partner_down)
+                       comp->sort_time = (comp->tsfp > comp->ends) ?
+                                         comp->tsfp : comp->ends;
+               else
+#endif
+                       comp->sort_time = comp->ends;
 
                break;
 
@@ -2096,7 +2139,7 @@ void expire_all_pools ()
                        }
 #if defined (FAILOVER_PROTOCOL)
                        if (p -> failover_peer &&
-                           l -> tstp > l -> tsfp &&
+                           l -> tstp > l -> atsfp &&
                            !(l -> flags & ON_UPDATE_QUEUE)) {
                                l -> desired_binding_state = l -> binding_state;
                                dhcp_failover_queue_update (l, 1);
index 74deaf75b8496eaa79d92b753c02856de8b1f9e8..41e87f477115be6d69e990ca36586923cb4fae0f 100644 (file)
@@ -3,7 +3,7 @@
    OMAPI object interfaces for the DHCP server. */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: omapi.c,v 1.54 2005/09/30 17:57:32 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: omapi.c,v 1.55 2006/02/24 23:16:32 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -482,6 +482,7 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
                                      omapi_object_t *id,
                                      omapi_object_t *h)
 {
+       u_int32_t bouncer;
        struct lease *lease;
        isc_result_t status;
 
@@ -604,63 +605,79 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
                        return status;
        }
 
+       /* TIME values may be 64-bit, depending on system architecture.
+        * OMAPI must be system independent, both in terms of transmitting
+        * bytes on the wire in network byte order, and in terms of being
+        * readable and usable by both systems.
+        *
+        * XXX: In a future feature release, a put_int64() should be made
+        * to exist, and perhaps a put_time() wrapper that selects which
+        * to use based upon sizeof(TIME).  In the meantime, use existing,
+        * 32-bit, code.
+        */
+       bouncer = (u_int32_t)lease->ends;
+       status = omapi_connection_put_name(c, "ends");
+       if (status != ISC_R_SUCCESS)
+               return status;
+       status = omapi_connection_put_uint32(c, sizeof(bouncer));
+       if (status != ISC_R_SUCCESS)
+               return status;
+       status = omapi_connection_put_uint32(c, bouncer);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
-       status = omapi_connection_put_name (c, "ends");
+       bouncer = (u_int32_t)lease->starts;
+       status = omapi_connection_put_name(c, "starts");
        if (status != ISC_R_SUCCESS)
                return status;
-       status = omapi_connection_put_uint32 (c, sizeof (TIME));
+       status = omapi_connection_put_uint32(c, sizeof(bouncer));
        if (status != ISC_R_SUCCESS)
                return status;
-       status = (omapi_connection_copyin
-                 (c, (const unsigned char *)&(lease -> ends), sizeof(TIME)));
+       status = omapi_connection_put_uint32(c, bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
-       status = omapi_connection_put_name (c, "starts");
+       bouncer = (u_int32_t)lease->tstp;
+       status = omapi_connection_put_name(c, "tstp");
        if (status != ISC_R_SUCCESS)
                return status;
-       status = omapi_connection_put_uint32 (c, sizeof (TIME));
+       status = omapi_connection_put_uint32(c, sizeof(bouncer));
        if (status != ISC_R_SUCCESS)
                return status;
-       status = (omapi_connection_copyin
-                 (c,
-                  (const unsigned char *)&(lease -> starts), sizeof (TIME)));
+       status = omapi_connection_put_uint32(c, bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
-       status = omapi_connection_put_name (c, "tstp");
+       bouncer = (u_int32_t)lease->tsfp;
+       status = omapi_connection_put_name(c, "tsfp");
        if (status != ISC_R_SUCCESS)
                return status;
-       status = omapi_connection_put_uint32 (c, sizeof (TIME));
+       status = omapi_connection_put_uint32(c, sizeof(bouncer));
        if (status != ISC_R_SUCCESS)
                return status;
-       status = (omapi_connection_copyin
-                 (c,
-                  (const unsigned char *)&(lease -> tstp), sizeof (TIME)));
+       status = omapi_connection_put_uint32(c, bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
-       status = omapi_connection_put_name (c, "tsfp");
+       bouncer = (u_int32_t)lease->atsfp;
+       status = omapi_connection_put_name(c, "atsfp");
        if (status != ISC_R_SUCCESS)
                return status;
-       status = omapi_connection_put_uint32 (c, sizeof (TIME));
+       status = omapi_connection_put_uint32(c, sizeof(bouncer));
        if (status != ISC_R_SUCCESS)
                return status;
-       status = (omapi_connection_copyin
-                 (c,
-                  (const unsigned char *)&(lease -> tsfp), sizeof (TIME)));
+       status = omapi_connection_put_uint32(c, bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
-       status = omapi_connection_put_name (c, "cltt");
+       bouncer = (u_int32_t)lease->cltt;
+       status = omapi_connection_put_name(c, "cltt");
        if (status != ISC_R_SUCCESS)
                return status;
-       status = omapi_connection_put_uint32 (c, sizeof (TIME));
+       status = omapi_connection_put_uint32(c, sizeof(bouncer));
        if (status != ISC_R_SUCCESS)
                return status;
-       status = (omapi_connection_copyin
-                 (c,
-                  (const unsigned char *)&(lease -> cltt), sizeof (TIME)));
+       status = omapi_connection_put_uint32(c, bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
index 49228e4b102b78fae528baf9b7153731036cae54..efaa7f0e139895b3d533e5505215fd0fc140e6bd 100644 (file)
@@ -3,7 +3,7 @@
    Memory allocation for the DHCP server... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: salloc.c,v 1.5 2005/03/17 20:15:29 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: salloc.c,v 1.6 2006/02/24 23:16:32 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"