]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Fix all the OMAPI objects in the DHCP server and client that weren't
authorTed Lemon <source@isc.org>
Tue, 16 May 2000 23:03:49 +0000 (23:03 +0000)
committerTed Lemon <source@isc.org>
Tue, 16 May 2000 23:03:49 +0000 (23:03 +0000)
  being correctly reference-counted.
- Make and use object-specific allocators.
- Add reference/dereference support to hash functions and to timeout
  functions.

48 files changed:
client/clparse.c
client/dhclient.c
client/omapi.c
common/Makefile.dist
common/alloc.c
common/bpf.c
common/conflex.c
common/discover.c
common/dispatch.c
common/dlpi.c
common/dns.c
common/execute.c
common/hash.c
common/icmp.c
common/lpf.c
common/memory.c
common/nit.c
common/options.c
common/parse.c
common/tables.c
common/upf.c
dhcpctl/dhcpctl.c
includes/dhcpd.h
includes/dhctoken.h
includes/failover.h
includes/hash.h
includes/omapip/omapip.h
includes/omapip/omapip_p.h
omapip/alloc.c
omapip/connection.c
omapip/dispatch.c
omapip/generic.c
omapip/listener.c
omapip/message.c
omapip/protocol.c
omapip/support.c
relay/dhcrelay.c
server/Makefile.dist
server/bootp.c
server/class.c
server/confpars.c
server/db.c
server/dhcp.c
server/dhcpd.c
server/failover.c
server/mdb.c
server/omapi.c
server/stables.c

index 7ecbbb996b253df5fd481a5887a7fa95da39c9fc..393df3fe28d8adaba3b6f65528531d9847be2ea4 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: clparse.c,v 1.43 2000/04/06 22:31:16 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: clparse.c,v 1.44 2000/05/16 23:01:57 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -97,11 +97,11 @@ isc_result_t read_client_conf ()
        top_level_config.script_name = "/etc/dhclient-script";
        top_level_config.requested_options = default_requested_options;
 
-       top_level_config.on_receipt = new_group (MDL);
+       group_allocate (&top_level_config.on_receipt, MDL);
        if (!top_level_config.on_receipt)
                log_fatal ("no memory for top-level on_receipt group");
 
-       top_level_config.on_transmission = new_group (MDL);
+       group_allocate (&top_level_config.on_transmission, MDL);
        if (!top_level_config.on_transmission)
                log_fatal ("no memory for top-level on_transmission group");
 
@@ -642,7 +642,7 @@ void parse_interface_declaration (cfile, outer_config, name)
                return;
        }
 
-       ip = interface_or_dummy (val);
+       interface_or_dummy (&ip, val);
 
        /* If we were given a name, this is a pseudo-interface. */
        if (name) {
@@ -687,37 +687,49 @@ void parse_interface_declaration (cfile, outer_config, name)
        token = next_token (&val, cfile);
 }
 
-struct interface_info *interface_or_dummy (name)
-       const char *name;
+int interface_or_dummy (struct interface_info **pi, const char *name)
 {
-       struct interface_info *ip;
+       struct interface_info *i;
+       struct interface_info *ip = (struct interface_info *)0;
 
        /* Find the interface (if any) that matches the name. */
-       for (ip = interfaces; ip; ip = ip -> next) {
-               if (!strcmp (ip -> name, name))
+       for (i = interfaces; i; i = i -> next) {
+               if (!strcmp (i -> name, name)) {
+                       interface_reference (&ip, i, MDL);
                        break;
+               }
        }
 
        /* If it's not a real interface, see if it's on the dummy list. */
        if (!ip) {
                for (ip = dummy_interfaces; ip; ip = ip -> next) {
-                       if (!strcmp (ip -> name, name))
+                       if (!strcmp (ip -> name, name)) {
+                               interface_reference (&ip, i, MDL);
                                break;
+                       }
                }
        }
 
        /* If we didn't find an interface, make a dummy interface as
           a placeholder. */
        if (!ip) {
-               ip = (struct interface_info *)dmalloc (sizeof *ip, MDL);
-               if (!ip)
-                       log_fatal ("No memory to record interface %s", name);
-               memset (ip, 0, sizeof *ip);
+               isc_result_t status;
+               status = interface_allocate (&ip, MDL);
+               if (status != ISC_R_SUCCESS)
+                       log_fatal ("Can't record interface %s: %s",
+                                  name, isc_result_totext (status));
                strcpy (ip -> name, name);
-               ip -> next = dummy_interfaces;
-               dummy_interfaces = ip;
+               if (dummy_interfaces) {
+                       interface_reference (&ip -> next,
+                                            dummy_interfaces, MDL);
+                       interface_dereference (&dummy_interfaces, MDL);
+               }
+               interface_reference (&dummy_interfaces, ip, MDL);
        }
-       return ip;
+       if (pi)
+               interface_reference (pi, ip, MDL);
+       interface_dereference (&ip, MDL);
+       return 1;
 }
 
 void make_client_state (state)
@@ -738,10 +750,11 @@ void make_client_config (client, config)
        if (!client -> config)
                log_fatal ("no memory for client config\n");
        memcpy (client -> config, config, sizeof *config);
-       client -> config -> on_receipt =
-               clone_group (config -> on_receipt, MDL);
-       client -> config -> on_transmission =
-               clone_group (config -> on_transmission, MDL);
+       if (!clone_group (&client -> config -> on_receipt,
+                         config -> on_receipt, MDL) ||
+           !clone_group (&client -> config -> on_transmission,
+                         config -> on_transmission, MDL))
+               log_fatal ("no memory for client state groups.");
 }
 
 /* client-lease-statement :==
@@ -918,8 +931,7 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
                        skip_to_semi (cfile);
                        break;
                }
-               ip = interface_or_dummy (val);
-               *ipp = ip;
+               interface_or_dummy (ipp, val);
                break;
 
              case NAME:
index 2a17098a148467bb42db448e3870443b1ec7626b..2e83b8cdee7892bae0f63d1fed9bad15fb276a0e 100644 (file)
@@ -15,7 +15,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
+ * 3. Neither the name of Internet Software Consortium nor the names
  *    of its contributors may be used to endorse or promote products derived
  *    from this software without specific prior written permission.
  *
@@ -41,7 +41,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.101 2000/05/01 17:15:23 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.102 2000/05/16 23:01:58 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -71,8 +71,7 @@ struct binding_scope global_scope;
    assert (state_is == state_shouldbe). */
 #define ASSERT_STATE(state_is, state_shouldbe) {}
 
-static char copyright[] =
-"Copyright 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.";
+static char copyright[] = "Copyright 1995-2000 Internet Software Consortium.";
 static char arr [] = "All rights reserved.";
 static char message [] = "Internet Software Consortium DHCP Client";
 static char contrib [] = "\nPlease contribute if you find this software useful.";
@@ -162,17 +161,20 @@ int main (argc, argv, envp)
                } else if (argv [i][0] == '-') {
                    usage ();
                } else {
-                   struct interface_info *tmp = ((struct interface_info *)
-                                                 dmalloc (sizeof *tmp, MDL));
-                   if (!tmp)
-                       log_fatal ("Insufficient memory to %s %s",
-                              "record interface", argv [i]);
-                   memset (tmp, 0, sizeof *tmp);
+                   struct interface_info *tmp = (struct interface_info *)0;
+                   status = interface_allocate (&tmp, MDL);
+                   if (status != ISC_R_SUCCESS)
+                       log_fatal ("Can't record interface %s:%s",
+                                  argv [i], isc_result_totext (status));
                    strcpy (tmp -> name, argv [i]);
-                   tmp -> next = interfaces;
+                   if (interfaces) {
+                           interface_reference (&tmp -> next,
+                                                interfaces, MDL);
+                           interface_dereference (&interfaces, MDL);
+                   }
+                   interface_reference (&interfaces, tmp, MDL);
                    tmp -> flags = INTERFACE_REQUESTED;
                    interfaces_requested = 1;
-                   interfaces = tmp;
                }
        }
 
@@ -267,7 +269,10 @@ int main (argc, argv, envp)
 
        /* Set up the OMAPI wrappers for various server database internal
           objects. */
-       dhclient_db_objects_setup ();
+       dhcp_common_objects_setup ();
+
+       dhcp_interface_discovery_hook = dhclient_interface_discovery_hook;
+       dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook;
 
        /* Discover all the network interfaces. */
        discover_interfaces (DISCOVER_UNCONFIGURED);
@@ -353,7 +358,7 @@ int main (argc, argv, envp)
                                /* Set up a timeout to start the initialization
                                   process. */
                                add_timeout (cur_time + random () % 5,
-                                            state_reboot, client);
+                                            state_reboot, client, 0, 0);
                        }
                }
        }
@@ -391,10 +396,10 @@ static void usage ()
                   "[-cf config-file] [interface]");
 }
 
-struct class *find_class (s)
-       const char *s;
+isc_result_t find_class (struct class **c,
+               const char *s, const char *file, int line)
 {
-       return (struct class *)0;
+       return 0;
 }
 
 int check_collection (packet, lease, collection)
@@ -418,10 +423,10 @@ int unbill_class (lease, class)
        return 0;
 }
 
-struct subnet *find_subnet (addr)
-       struct iaddr addr;
+int find_subnet (struct subnet **sp,
+                struct iaddr addr, const char *file, int line)
 {
-       return (struct subnet *)0;
+       return 0;
 }
 
 /* Individual States:
@@ -781,7 +786,7 @@ void bind_lease (client)
 
        /* Set up a timeout to start the renewal process. */
        add_timeout (client -> active -> renewal,
-                    state_bound, client);
+                    state_bound, client, 0, 0);
 
        log_info ("bound to %s -- renewal in %ld seconds.",
              piaddr (client -> active -> address),
@@ -1025,7 +1030,7 @@ void dhcpoffer (packet)
        if (stop_selecting <= 0)
                state_selecting (ip);
        else {
-               add_timeout (stop_selecting, state_selecting, client);
+               add_timeout (stop_selecting, state_selecting, client, 0, 0);
                cancel_timeout (send_discover, client);
        }
 }
@@ -1269,7 +1274,8 @@ void send_discover (cpp)
                              inaddr_any, &sockaddr_broadcast,
                              (struct hardware *)0);
 
-       add_timeout (cur_time + client -> interval, send_discover, client);
+       add_timeout (cur_time + client -> interval,
+                    send_discover, client, 0, 0);
 }
 
 /* state_panic gets called if we haven't received any offers in a preset
@@ -1317,7 +1323,7 @@ void state_panic (cpp)
                                          (long)(client -> active -> renewal -
                                                 cur_time), "seconds");
                                add_timeout (client -> active -> renewal,
-                                            state_bound, client);
+                                            state_bound, client, 0, 0);
                            } else {
                                client -> state = S_BOUND;
                                log_info ("bound: immediate renewal.");
@@ -1369,7 +1375,7 @@ void state_panic (cpp)
        add_timeout (cur_time +
                     ((client -> config -> retry_interval + 1) / 2 +
                      (random () % client -> config -> retry_interval)),
-                    state_init, client);
+                    state_init, client, 0, 0);
        go_daemon ();
 }
 
@@ -1523,7 +1529,7 @@ void send_request (cpp)
                                      (struct hardware *)0);
 
        add_timeout (cur_time + client -> interval,
-                    send_request, client);
+                    send_request, client, 0, 0);
 }
 
 void send_decline (cpp)
@@ -2383,7 +2389,54 @@ void do_release(client)
        }
 }
 
+int dhclient_interface_shutdown_hook (struct interface_info *interface)
+{
+       do_release (interface -> client);
+       return 1;
+}
 
+int dhclient_interface_discovery_hook (struct interface_info *tmp)
+{
+       struct interface_info *last, *ip;
+       /* See if we can find the client from dummy_interfaces */
+       last = 0;
+       for (ip = dummy_interfaces; ip; ip = ip -> next) {
+               if (!strcmp (ip -> name, tmp -> name)) {
+                       /* Remove from dummy_interfaces */
+                       if (last) {
+                               ip = (struct interface_info *)0;
+                               interface_reference (&ip, last -> next, MDL);
+                               interface_dereference (&last -> next, MDL);
+                               if (ip -> next) {
+                                       interface_reference (&last -> next,
+                                                            ip -> next, MDL);
+                                       interface_dereference (&ip -> next,
+                                                              MDL);
+                               }
+                       } else {
+                               ip = (struct interface_info *)0;
+                               interface_reference (&ip,
+                                                    dummy_interfaces, MDL);
+                               interface_dereference (&dummy_interfaces, MDL);
+                               if (ip -> next) {
+                                       interface_reference (&dummy_interfaces,
+                                                            ip -> next, MDL);
+                                       interface_dereference (&ip -> next,
+                                                              MDL);
+                               }
+                       }
+                       /* Copy "client" to tmp */
+                       if (ip -> client) {
+                               tmp -> client = ip -> client;
+                               tmp -> client -> interface = tmp;
+                       }
+                       interface_dereference (&ip, MDL);
+                       break;
+               }
+               last = ip;
+       }
+       return 1;
+}
 
 /* The client should never receive a relay agent information option,
    so if it does, log it and discard it. */
index fa1ec845644069412534330211b4e6f572ca42f0..fc9e4e2ef86987d5ed818b25aa140d4a142bbc09 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: omapi.c,v 1.4 2000/03/17 03:58:56 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: omapi.c,v 1.5 2000/05/16 23:02:00 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 #include <omapip/omapip_p.h>
-
-void dhclient_db_objects_setup ()
-{
-       isc_result_t status;
-
-       status = omapi_object_type_register (&dhcp_type_interface,
-                                            "interface",
-                                            dhclient_interface_set_value,
-                                            dhclient_interface_get_value,
-                                            dhclient_interface_destroy,
-                                            dhclient_interface_signal_handler,
-                                            dhclient_interface_stuff_values,
-                                            dhclient_interface_lookup, 
-                                            dhclient_interface_create,
-                                            dhclient_interface_remove);
-       if (status != ISC_R_SUCCESS)
-               log_fatal ("Can't register interface object type: %s",
-                          isc_result_totext (status));
-
-}
-
-isc_result_t dhclient_interface_set_value  (omapi_object_t *h,
-                                           omapi_object_t *id,
-                                           omapi_data_string_t *name,
-                                           omapi_typed_data_t *value)
-{
-       struct interface_info *interface;
-       isc_result_t status;
-       int foo;
-
-       if (h -> type != dhcp_type_interface)
-               return ISC_R_INVALIDARG;
-       interface = (struct interface_info *)h;
-
-       if (!omapi_ds_strcmp (name, "name")) {
-               if (value -> type == omapi_datatype_data ||
-                   value -> type == omapi_datatype_string) {
-                       memcpy (interface -> name,
-                               value -> u.buffer.value,
-                               value -> u.buffer.len);
-                       interface -> name [value -> u.buffer.len] = 0;
-               } else
-                       return ISC_R_INVALIDARG;
-               return ISC_R_SUCCESS;
-       }
-
-       /* Try to find some inner object that can take the value. */
-       if (h -> inner && h -> inner -> type -> set_value) {
-               status = ((*(h -> inner -> type -> set_value))
-                         (h -> inner, id, name, value));
-               if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
-                       return status;
-       }
-                         
-       return ISC_R_NOTFOUND;
-}
-
-
-isc_result_t dhclient_interface_get_value (omapi_object_t *h,
-                                          omapi_object_t *id,
-                                          omapi_data_string_t *name,
-                                          omapi_value_t **value)
-{
-       return ISC_R_NOTIMPLEMENTED;
-}
-
-isc_result_t dhclient_interface_destroy (omapi_object_t *h,
-                                        const char *file, int line)
-{
-       struct interface_info *interface;
-       isc_result_t status;
-
-       if (h -> type != dhcp_type_interface)
-               return ISC_R_INVALIDARG;
-       interface = (struct interface_info *)h;
-
-       
-       if (interface -> ifp)
-               free (interface -> ifp);
-       dfree (interface, file, line);
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t dhclient_interface_signal_handler (omapi_object_t *h,
-                                               const char *name, va_list ap)
-{
-       struct interface_info *ip, *interface;
-       struct client_config *config;
-       struct client_state *client;
-
-       if (h -> type != dhcp_type_interface)
-               return ISC_R_INVALIDARG;
-       interface = (struct interface_info *)h;
-
-       interface -> next = interfaces;
-       interfaces = interface;
-
-       discover_interfaces (DISCOVER_UNCONFIGURED);
-
-       for (ip = interfaces; ip; ip = ip -> next) {
-               /* If interfaces were specified, don't configure
-                  interfaces that weren't specified! */
-               if (ip -> flags & INTERFACE_RUNNING ||
-                  (ip -> flags & (INTERFACE_REQUESTED |
-                                    INTERFACE_AUTOMATIC)) !=
-                    INTERFACE_REQUESTED)
-                       continue;
-               script_init (ip -> client,
-                            "PREINIT", (struct string_list *)0);
-               if (ip -> client -> alias)
-                       script_write_params (ip -> client, "alias_",
-                                            ip -> client -> alias);
-               script_go (ip -> client);
-       }
-       
-       discover_interfaces (interfaces_requested
-                            ? DISCOVER_REQUESTED
-                            : DISCOVER_RUNNING);
-
-       for (ip = interfaces; ip; ip = ip -> next) {
-               if (ip -> flags & INTERFACE_RUNNING)
-                       continue;
-               ip -> flags |= INTERFACE_RUNNING;
-               for (client = ip -> client; client; client = client -> next) {
-                       client -> state = S_INIT;
-                       /* Set up a timeout to start the initialization
-                          process. */
-                       add_timeout (cur_time + random () % 5,
-                                    state_reboot, client);
-               }
-       }
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t dhclient_interface_stuff_values (omapi_object_t *c,
-                                             omapi_object_t *id,
-                                             omapi_object_t *h)
-{
-       struct interface_info *interface;
-       isc_result_t status;
-
-       if (h -> type != dhcp_type_interface)
-               return ISC_R_INVALIDARG;
-       interface = (struct interface_info *)h;
-
-       /* Write out all the values. */
-
-       status = omapi_connection_put_name (c, "state");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       if (interface -> flags && INTERFACE_REQUESTED)
-           status = omapi_connection_put_string (c, "up");
-       else
-           status = omapi_connection_put_string (c, "down");
-       if (status != ISC_R_SUCCESS)
-               return status;
-
-       /* Write out the inner object, if any. */
-       if (h -> inner && h -> inner -> type -> stuff_values) {
-               status = ((*(h -> inner -> type -> stuff_values))
-                         (c, id, h -> inner));
-               if (status == ISC_R_SUCCESS)
-                       return status;
-       }
-
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t dhclient_interface_lookup (omapi_object_t **ip,
-                                       omapi_object_t *id,
-                                       omapi_object_t *ref)
-{
-       omapi_value_t *tv = (omapi_value_t *)0;
-       isc_result_t status;
-       struct interface_info *interface;
-
-       /* First see if we were sent a handle. */
-       status = omapi_get_value_str (ref, id, "handle", &tv);
-       if (status == ISC_R_SUCCESS) {
-               status = omapi_handle_td_lookup (ip, tv -> value);
-
-               omapi_value_dereference (&tv, MDL);
-               if (status != ISC_R_SUCCESS)
-                       return status;
-
-               /* Don't return the object if the type is wrong. */
-               if ((*ip) -> type != dhcp_type_interface) {
-                       omapi_object_dereference (ip, MDL);
-                       return ISC_R_INVALIDARG;
-               }
-       }
-
-       /* Now look for an interface name. */
-       status = omapi_get_value_str (ref, id, "name", &tv);
-       if (status == ISC_R_SUCCESS) {
-               for (interface = interfaces; interface;
-                    interface = interface -> next) {
-                   if (strncmp (interface -> name,
-                                (char *)tv -> value -> u.buffer.value,
-                                tv -> value -> u.buffer.len) == 0)
-                           break;
-               }
-               omapi_value_dereference (&tv, MDL);
-               if (*ip && *ip != (omapi_object_t *)interface) {
-                       omapi_object_dereference (ip, MDL);
-                       return ISC_R_KEYCONFLICT;
-               } else if (!interface) {
-                       if (*ip)
-                               omapi_object_dereference (ip, MDL);
-                       return ISC_R_NOTFOUND;
-               } else if (!*ip)
-                       /* XXX fix so that hash lookup itself creates
-                          XXX the reference. */
-                       omapi_object_reference (ip,
-                                               (omapi_object_t *)interface,
-                                               MDL);
-       }
-
-       /* If we get to here without finding an interface, no valid key was
-          specified. */
-       if (!*ip)
-               return ISC_R_NOKEYS;
-       return ISC_R_SUCCESS;
-}
-
-/* actually just go discover the interface */
-isc_result_t dhclient_interface_create (omapi_object_t **lp,
-                                       omapi_object_t *id)
-{
-       struct interface_info *hp;
-       
-       hp = (struct interface_info *)dmalloc (sizeof (struct interface_info),
-                                              MDL);
-       if (!hp)
-               return ISC_R_NOMEMORY;
-       memset (hp, 0, sizeof *hp);
-       hp -> refcnt = 0;
-       hp -> type = dhcp_type_interface;
-       hp -> flags = INTERFACE_REQUESTED;
-       return omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
-
-}
-
-isc_result_t dhclient_interface_remove (omapi_object_t *lp,
-                                       omapi_object_t *id)
-{
-       struct interface_info *interface, *ip, *last;
-
-       interface = (struct interface_info *)lp;
-
-       /* remove from interfaces */
-       last = 0;
-       for (ip = interfaces; ip; ip = ip -> next) {
-               if (!strcmp (ip -> name, interface -> name)) {
-                       if (last)
-                               last -> next = ip -> next;
-                       else
-                               interfaces = ip -> next;
-                       break;
-               }
-               last = ip;
-       }
-
-       /* add the interface to the dummy_interface list */
-       interface -> next = dummy_interfaces;
-       dummy_interfaces = interface;
-
-       /* do a DHCPRELEASE */
-       do_release (interface -> client);
-
-       /* remove the io object */
-       omapi_io_destroy (interface -> outer, MDL);
-
-       if_deregister_send (interface);
-       if_deregister_receive (interface);
-
-       return ISC_R_SUCCESS;
-}
index af5a451bfa04945800aaf2e5130185a2b73681e8..5c199d6952c51c2811358e913a50cb2f72ac67db 100644 (file)
@@ -22,11 +22,11 @@ SEDMANPAGES = dhcp-options.man5 dhcp-contrib.man5 dhcp-eval.man5
 SRC    = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
         lpf.c dlpi.c packet.c tr.c ethernet.c memory.c print.c options.c \
         inet.c convert.c tree.c tables.c hash.c alloc.c fddi.c \
-        inet_addr.c dns.c resolv.c execute.c discover.c auth.c
+        inet_addr.c dns.c resolv.c execute.c discover.c comapi.c
 OBJ    = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
         lpf.o dlpi.o packet.o tr.o ethernet.o memory.o print.o options.o \
         inet.o convert.o tree.o tables.o hash.o alloc.o fddi.o \
-        inet_addr.o dns.o resolv.o execute.o discover.o auth.o
+        inet_addr.o dns.o resolv.o execute.o discover.o comapi.o
 MAN    = dhcp-options.5 dhcp-contrib.5 dhcp-eval.5
 
 DEBUG  = -g
index 592c863aa538abcc464c418b1ddff7389d47aff1..8d2a17049b841a8dd51c595990380b55cc502560 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: alloc.c,v 1.46 2000/03/17 03:59:00 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: alloc.c,v 1.47 2000/05/16 23:02:08 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -52,91 +52,161 @@ static char copyright[] =
 struct dhcp_packet *dhcp_free_list;
 struct packet *packet_free_list;
 
-struct dhcp_packet *new_dhcp_packet (file, line)
-       const char *file;
-       int line;
-{
-       struct dhcp_packet *rval;
-       rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
-                                             file, line);
-       return rval;
-}
+OMAPI_OBJECT_ALLOC (subnet, struct subnet, dhcp_type_subnet)
+OMAPI_OBJECT_ALLOC (shared_network, struct shared_network,
+                   dhcp_type_shared_network)
+OMAPI_OBJECT_ALLOC (group_object, struct group_object, dhcp_type_group)
 
-struct hash_table *new_hash_table (count, file, line)
-       int count;
+int group_allocate (ptr, file, line)
+       struct group **ptr;
        const char *file;
        int line;
 {
-       struct hash_table *rval = dmalloc (sizeof (struct hash_table)
-                                          - (DEFAULT_HASH_SIZE
-                                             * sizeof (struct hash_bucket *))
-                                          + (count
-                                             * sizeof (struct hash_bucket *)),
-                                          file, line);
-       rval -> hash_count = count;
-       return rval;
-}
+       int size;
 
-struct hash_bucket *new_hash_bucket (file, line)
-       const char *file;
-       int line;
-{
-       struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket),
-                                           file, line);
-       return rval;
+       if (!ptr) {
+               log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+       if (*ptr) {
+               log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               *ptr = (struct group *)0;
+#endif
+       }
+
+       *ptr = dmalloc (sizeof **ptr, file, line);
+       if (*ptr) {
+               memset (*ptr, 0, sizeof **ptr);
+               (*ptr) -> refcnt = 1;
+               return 1;
+       }
+       return 0;
 }
 
-struct lease *new_leases (n, file, line)
-       unsigned n;
+int group_reference (ptr, bp, file, line)
+       struct group **ptr;
+       struct group *bp;
        const char *file;
        int line;
 {
-       struct lease *rval = dmalloc (n * sizeof (struct lease), file, line);
-       return rval;
+       if (!ptr) {
+               log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+       if (*ptr) {
+               log_error ("%s(%d): non-null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               *ptr = (struct group *)0;
+#endif
+       }
+       *ptr = bp;
+       bp -> refcnt++;
+       rc_register (file, line, ptr, bp, bp -> refcnt);
+       dmalloc_reuse (bp, file, line, 1);
+       return 1;
 }
 
-struct lease *new_lease (file, line)
+int group_dereference (ptr, file, line)
+       struct group **ptr;
        const char *file;
        int line;
 {
-       struct lease *rval = dmalloc (sizeof (struct lease), file, line);
-       return rval;
+       int i;
+       struct group *group;
+
+       if (!ptr || !*ptr) {
+               log_error ("%s(%d): null pointer", file, line);
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+
+       group = *ptr;
+       *ptr = (struct group *)0;
+       --group -> refcnt;
+       rc_register (file, line, ptr, group, group -> refcnt);
+       if (group -> refcnt > 0)
+               return 1;
+
+       if (group -> refcnt < 0) {
+               log_error ("%s(%d): negative refcnt!", file, line);
+#if defined (DEBUG_RC_HISTORY)
+               dump_rc_history ();
+#endif
+#if defined (POINTER_DEBUG)
+               abort ();
+#else
+               return 0;
+#endif
+       }
+
+       if (group -> object)
+               group_object_dereference (&group -> object, MDL);
+       if (group -> subnet)    
+               subnet_dereference (&group -> subnet, MDL);
+       if (group -> shared_network)
+               shared_network_dereference (&group -> shared_network, MDL);
+       if (group -> statements)
+               executable_statement_dereference (&group -> statements, MDL);
+       dfree (group, file, line);
+       return 1;
 }
 
-struct subnet *new_subnet (file, line)
+struct dhcp_packet *new_dhcp_packet (file, line)
        const char *file;
        int line;
 {
-       struct subnet *rval = dmalloc (sizeof (struct subnet), file, line);
+       struct dhcp_packet *rval;
+       rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
+                                             file, line);
        return rval;
 }
 
-struct class *new_class (file, line)
+struct hash_table *new_hash_table (count, file, line)
+       int count;
        const char *file;
        int line;
 {
-       struct class *rval = dmalloc (sizeof (struct class), file, line);
+       struct hash_table *rval = dmalloc (sizeof (struct hash_table)
+                                          - (DEFAULT_HASH_SIZE
+                                             * sizeof (struct hash_bucket *))
+                                          + (count
+                                             * sizeof (struct hash_bucket *)),
+                                          file, line);
+       rval -> hash_count = count;
        return rval;
 }
 
-struct shared_network *new_shared_network (file, line)
+struct hash_bucket *new_hash_bucket (file, line)
        const char *file;
        int line;
 {
-       struct shared_network *rval =
-               dmalloc (sizeof (struct shared_network), file, line);
+       struct hash_bucket *rval = dmalloc (sizeof (struct hash_bucket),
+                                           file, line);
        return rval;
 }
 
-struct group *new_group (file, line)
+void free_hash_bucket (ptr, file, line)
+       struct hash_bucket *ptr;
        const char *file;
        int line;
 {
-       struct group *rval =
-               dmalloc (sizeof (struct group), file, line);
-       if (rval)
-               memset (rval, 0, sizeof *rval);
-       return rval;
+       dfree ((VOIDPTR)ptr, file, line);
 }
 
 struct protocol *new_protocol (file, line)
@@ -147,32 +217,6 @@ struct protocol *new_protocol (file, line)
        return rval;
 }
 
-struct lease_state *free_lease_states;
-
-struct lease_state *new_lease_state (file, line)
-       const char *file;
-       int line;
-{
-       struct lease_state *rval;
-
-       if (free_lease_states) {
-               rval = free_lease_states;
-               free_lease_states =
-                       (struct lease_state *)(free_lease_states -> next);
-               dmalloc_reuse (rval, file, line, 0);
-       } else {
-               rval = dmalloc (sizeof (struct lease_state), file, line);
-               if (!rval)
-                       return rval;
-       }
-       memset (rval, 0, sizeof *rval);
-       if (!option_state_allocate (&rval -> options, file, line)) {
-               free_lease_state (rval, file, line);
-               return (struct lease_state *)0;
-       }
-       return rval;
-}
-
 struct domain_search_list *new_domain_search_list (file, line)
        const char *file;
        int line;
@@ -248,23 +292,6 @@ void free_domain_search_list (ptr, file, line)
        dfree ((VOIDPTR)ptr, file, line);
 }
 
-void free_lease_state (ptr, file, line)
-       struct lease_state *ptr;
-       const char *file;
-       int line;
-{
-       if (ptr -> options)
-               option_state_dereference (&ptr -> options, file, line);
-       if (ptr -> packet)
-               packet_dereference (&ptr -> packet, file, line);
-       data_string_forget (&ptr -> parameter_request_list, file, line);
-       data_string_forget (&ptr -> filename, file, line);
-       data_string_forget (&ptr -> server_name, file, line);
-       ptr -> next = free_lease_states;
-       free_lease_states = ptr;
-       dmalloc_reuse (free_lease_states, (char *)0, 0, 0);
-}
-
 void free_protocol (ptr, file, line)
        struct protocol *ptr;
        const char *file;
@@ -273,54 +300,6 @@ void free_protocol (ptr, file, line)
        dfree ((VOIDPTR)ptr, file, line);
 }
 
-void free_group (ptr, file, line)
-       struct group *ptr;
-       const char *file;
-       int line;
-{
-       dfree ((VOIDPTR)ptr, file, line);
-}
-
-void free_shared_network (ptr, file, line)
-       struct shared_network *ptr;
-       const char *file;
-       int line;
-{
-       dfree ((VOIDPTR)ptr, file, line);
-}
-
-void free_class (ptr, file, line)
-       struct class *ptr;
-       const char *file;
-       int line;
-{
-       dfree ((VOIDPTR)ptr, file, line);
-}
-
-void free_subnet (ptr, file, line)
-       struct subnet *ptr;
-       const char *file;
-       int line;
-{
-       dfree ((VOIDPTR)ptr, file, line);
-}
-
-void free_lease (ptr, file, line)
-       struct lease *ptr;
-       const char *file;
-       int line;
-{
-       dfree ((VOIDPTR)ptr, file, line);
-}
-
-void free_hash_bucket (ptr, file, line)
-       struct hash_bucket *ptr;
-       const char *file;
-       int line;
-{
-       dfree ((VOIDPTR)ptr, file, line);
-}
-
 void free_hash_table (ptr, file, line)
        struct hash_table *ptr;
        const char *file;
@@ -353,26 +332,6 @@ void free_client_lease (lease, file, line)
        dfree (lease, file, line);
 }
 
-struct pool *new_pool (file, line)
-       const char *file;
-       int line;
-{
-       struct pool *pool = ((struct pool *)
-                            dmalloc (sizeof (struct pool), file, line));
-       if (!pool)
-               return pool;
-       memset (pool, 0, sizeof *pool);
-       return pool;
-}
-
-void free_pool (pool, file, line)
-       struct pool *pool;
-       const char *file;
-       int line;
-{
-       dfree (pool, file, line);
-}
-
 struct auth_key *new_auth_key (len, file, line)
        unsigned len;
        const char *file;
@@ -396,26 +355,6 @@ void free_auth_key (peer, file, line)
        dfree (peer, file, line);
 }
 
-struct permit *new_permit (file, line)
-       const char *file;
-       int line;
-{
-       struct permit *permit = ((struct permit *)
-                                dmalloc (sizeof (struct permit), file, line));
-       if (!permit)
-               return permit;
-       memset (permit, 0, sizeof *permit);
-       return permit;
-}
-
-void free_permit (permit, file, line)
-       struct permit *permit;
-       const char *file;
-       int line;
-{
-       dfree (permit, file, line);
-}
-
 pair free_pairs;
 
 pair new_pair (file, line)
@@ -1095,6 +1034,8 @@ int packet_dereference (ptr, file, line)
 
        if (packet -> options)
                option_state_dereference (&packet -> options, file, line);
+       if (packet -> interface)
+               interface_dereference (&packet -> interface, MDL);
        packet -> raw = (struct dhcp_packet *)free_packets;
        free_packets = packet;
        dmalloc_reuse (free_packets, (char *)0, 0, 0);
index a07e40e5ee34abfaaf00618b8f466037efaabb9e..f1a40f4f4a65b325353623b3f746b9aa819ce512 100644 (file)
@@ -47,7 +47,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: bpf.c,v 1.38 2000/04/14 16:17:35 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: bpf.c,v 1.39 2000/05/16 23:02:09 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -515,12 +515,9 @@ int can_receive_unicast_unconfigured (ip)
 void maybe_setup_fallback ()
 {
        isc_result_t status;
-       struct interface_info *fbi;
-       fbi = setup_fallback ();
-       if (fbi) {
+       struct interface_info *fbi = (struct interface_info *)0;
+       if (setup_fallback (&fbi, MDL)) {
                if_register_fallback (fbi);
-               fbi -> refcnt = 1;
-               fbi -> type = dhcp_type_interface;
                status = omapi_register_io_object ((omapi_object_t *)fbi,
                                                   if_readsocket, 0,
                                                   fallback_discard, 0, 0);
index 1074a37a45673bbb06ba0dd27831c1e0d28f469d..ca6943a5fc8c98f2966f967fb480d2a06648be05 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.74 2000/05/04 18:57:57 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.75 2000/05/16 23:02:11 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -671,6 +671,8 @@ static enum dhcp_token intern (atom, dfv)
                        return HOSTNAME;
                break;
              case 'i':
+               if (!strcasecmp (atom + 1, "nclude"))
+                       return INCLUDE;
                if (!strcasecmp (atom + 1, "nteger"))
                        return INTEGER;
                if (!strcasecmp (atom + 1, "nfinite"))
index 35708416fe01a5a2d77aad5b870edcd7d24a9117..c2df1a7ea365005533102d51bcb51f942b25a405 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: discover.c,v 1.26 2000/05/01 17:31:19 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: discover.c,v 1.27 2000/05/16 23:02:12 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -54,6 +54,8 @@ extern int interfaces_invalidated;
 int quiet_interface_discovery;
 u_int16_t local_port;
 u_int16_t remote_port;
+int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *);
+int (*dhcp_interface_discovery_hook) (struct interface_info *);
 
 struct in_addr limited_broadcast;
 struct in_addr local_address;
@@ -65,6 +67,8 @@ void (*bootp_packet_handler) PROTO ((struct interface_info *,
 
 omapi_object_type_t *dhcp_type_interface;
 
+OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface)
+
 /* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
    For each interface that's of type INET and not the loopback interface,
    register that interface with the network I/O software, figure out what
@@ -97,7 +101,8 @@ void discover_interfaces (state)
                        (&dhcp_type_interface, "interface",
                         interface_set_value, interface_get_value,
                         interface_destroy, interface_signal_handler,
-                        interface_stuff_values, 0, 0, 0);
+                        interface_stuff_values, 0, 0, 0, 0, 0,
+                        sizeof (struct interface_info));
                if (status != ISC_R_SUCCESS)
                        log_fatal ("Can't create interface object type: %s",
                                   isc_result_totext (status));
@@ -172,45 +177,31 @@ void discover_interfaces (state)
                /* If there isn't already an interface by this name,
                   allocate one. */
                if (!tmp) {
-                       tmp = ((struct interface_info *) dmalloc (sizeof *tmp,
-                                                                 MDL));
-                       if (!tmp)
-                               log_fatal ("Insufficient memory to %s %s",
-                                      "record interface", ifp -> ifr_name);
-                       memset (tmp, 0, sizeof *tmp);
+                       tmp = (struct interface_info *)0;
+                       status = interface_allocate (&tmp, MDL);
+                       if (status != ISC_R_SUCCESS)
+                               log_fatal ("Error allocating interface %s: %s",
+                                          ifp -> ifr_name,
+                                          isc_result_totext (status));
                        strcpy (tmp -> name, ifp -> ifr_name);
                        tmp -> circuit_id = (u_int8_t *)tmp -> name;
                        tmp -> circuit_id_len = strlen (tmp -> name);
                        tmp -> remote_id = 0;
                        tmp -> remote_id_len = 0;
-                       tmp -> next = interfaces;
                        tmp -> flags = ir;
-                       interfaces = tmp;
-               }
-
-               /* See if we can find the client from dummy_interfaces */
-               last = 0;
-               for (ip = dummy_interfaces; ip; ip = ip -> next) {
-                       if (!strcmp (ip -> name, tmp -> name)) {
-                               /* Remove from dummy_interfaces */
-                               if (last)
-                                       last -> next = ip -> next;
-                               else
-                                       dummy_interfaces = ip -> next;
-                               /* Copy "client" to tmp */
-                               if (ip -> client) {
-                                       tmp -> client = ip -> client;
-                                       tmp -> client -> interface = tmp;
-                               }
-                               /* free up the dummy_interface */
-                               if (ip -> ifp)
-                                       free (ip -> ifp);
-                               dfree (ip, MDL);
-                               break;
+                       if (interfaces) {
+                               interface_reference (&tmp -> next,
+                                                    interfaces, MDL);
+                               interface_dereference (&interfaces, MDL);
                        }
-                       last = ip;
+                       interface_reference (&interfaces, tmp, MDL);
+                       interface_dereference (&tmp, MDL);
+                       tmp = interfaces;
                }
 
+               if (dhcp_interface_discovery_hook)
+                       (*dhcp_interface_discovery_hook) (tmp);
+
                /* If we have the capability, extract link information
                   and record it in a linked list. */
 #ifdef HAVE_AF_LINK
@@ -265,56 +256,17 @@ void discover_interfaces (state)
                        addr.len = 4;
                        memcpy (addr.iabuf, &foo.sin_addr.s_addr,
                                addr.len);
-
-                       /* If there's a registered subnet for this address,
-                          connect it together... */
-                       if ((subnet = find_subnet (addr))) {
-                               /* If this interface has multiple aliases
-                                  on the same subnet, ignore all but the
-                                  first we encounter. */
-                               if (!subnet -> interface) {
-                                       subnet -> interface = tmp;
-                                       subnet -> interface_address = addr;
-                               } else if (subnet -> interface != tmp) {
-                                       log_error ("Multiple %s %s: %s %s", 
-                                             "interfaces match the",
-                                             "same subnet",
-                                             subnet -> interface -> name,
-                                             tmp -> name);
-                               }
-                               share = subnet -> shared_network;
-                               if (tmp -> shared_network &&
-                                   tmp -> shared_network != share) {
-                                       log_fatal ("Interface %s matches %s",
-                                                  tmp -> name,
-                                                  "multiple shared networks");
-                               } else {
-                                       tmp -> shared_network = share;
-                               }
-
-                               if (!share -> interface) {
-                                       share -> interface = tmp;
-                               } else if (share -> interface != tmp) {
-                                       log_error ("Multiple %s %s: %s %s", 
-                                             "interfaces match the",
-                                             "same shared network",
-                                             share -> interface -> name,
-                                             tmp -> name);
-                               }
-                       }
+                       if (dhcp_interface_setup_hook)
+                               (*dhcp_interface_setup_hook) (tmp, &addr);
                }
        }
 
 #if defined (LINUX_SLASHPROC_DISCOVERY)
-       /* On Linux, interfaces that don't have IP addresses don't show up
-          in the SIOCGIFCONF syscall.   We got away with this prior to
-          Linux 2.1 because we would give each interface an IP address of
-          0.0.0.0 before trying to boot, but that doesn't work after 2.1
-          because we're using LPF, because we can't configure interfaces
-          with IP addresses of 0.0.0.0 anymore (grumble).   This only
-          matters for the DHCP client, of course - the relay agent and
-          server should only care about interfaces that are configured
-          with IP addresses anyway.
+       /* On Linux, interfaces that don't have IP addresses don't
+          show up in the SIOCGIFCONF syscall.  This only matters for
+          the DHCP client, of course - the relay agent and server
+          should only care about interfaces that are configured with
+          IP addresses anyway.
 
           The PROCDEV_DEVICE (/proc/net/dev) is a kernel-supplied file
           that, when read, prints a human readable network status.   We
@@ -322,8 +274,7 @@ void discover_interfaces (state)
           two lines (which are header) and then parsing off everything
           up to the colon in each subsequent line - these lines start
           with the interface name, then a colon, then a bunch of
-          statistics.   Yes, Virgina, this is a kludge, but you work
-          with what you have. */
+          statistics. */
 
        if (state == DISCOVER_UNCONFIGURED) {
                FILE *proc_dev;
@@ -362,38 +313,21 @@ void discover_interfaces (state)
                                continue;
 
                        /* Otherwise, allocate one. */
-                       tmp = ((struct interface_info *)
-                              dmalloc (sizeof *tmp, MDL));
-                       if (!tmp)
-                               log_fatal ("Insufficient memory to %s %s",
-                                          "record interface", name);
-                       memset (tmp, 0, sizeof *tmp);
-                       strcpy (tmp -> name, name);
-
+                       tmp = (struct interface_info *)0;
+                       status = interface_allocate (&tmp, MDL);
+                       if (status != ISC_R_SUCCESS)
+                               log_fatal ("Can't allocate interface %s: %s",
+                                          name, isc_result_totext (status));
                        tmp -> flags = ir;
-                       tmp -> next = interfaces;
-                       interfaces = tmp;
-                       /* See if we can find the client from dummy_interfaces */
-                       last = 0;
-                       for (ip = dummy_interfaces; ip; ip = ip -> next) {
-                               if (!strcmp (ip -> name, tmp -> name)) {
-                                       /* remove from dummy_interfaces */
-                                       if (last)
-                                               last -> next = ip -> next;
-                                       else
-                                               dummy_interfaces = ip -> next;
-                                       /* copy "client" to tmp */
-                                       if (ip -> client)
-                                               tmp -> client = ip -> client;
-                                       /* free up the dummy_interface */
-                                       if (ip -> ifp)
-                                               free (ip -> ifp);
-                                       dfree (ip, MDL);
-                                       ip = 0;
-                                       break;
-                               }
-                               last = ip;
-                       }
+                       interface_reference (&tmp -> next, interfaces, MDL);
+                       interface_dereference (&interfaces, MDL);
+                       interface_reference (&interfaces, tmp, MDL);
+                       interface_dereference (&tmp, MDL);
+                       tmp = interfaces;
+
+                       if (interface_discovery_hook)
+                               (*interface_discovery_hook (tmp);
+
                }
                fclose (proc_dev);
        }
@@ -503,9 +437,14 @@ void discover_interfaces (state)
        }
 
        /* Weed out the interfaces that did not have IP addresses. */
-       last = (struct interface_info *)0;
-       for (tmp = interfaces; tmp; tmp = next) {
-               next = tmp -> next;
+       tmp = last = next = (struct interface_info *)0;
+       if (interfaces)
+               interface_reference (&tmp, interfaces, MDL);
+       while (tmp) {
+               if (next)
+                       interface_dereference (&next, MDL);
+               if (tmp -> next)
+                       interface_reference (&next, tmp -> next, MDL);
                /* skip interfaces that are running already */
                if (tmp -> flags & INTERFACE_RUNNING)
                        continue;
@@ -516,15 +455,29 @@ void discover_interfaces (state)
                if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
                        if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
                                log_fatal ("%s: not found", tmp -> name);
-                       if (!last)
-                               interfaces = interfaces -> next;
-                       else
-                               last -> next = tmp -> next;
+                       if (!last) {
+                               if (interfaces)
+                                       interface_dereference (&interfaces,
+                                                              MDL);
+                               interface_reference (&interfaces, next, MDL);
+                       } else {
+                               interface_dereference (&last -> next, MDL);
+                               interface_reference (&last -> next, next, MDL);
+                       }
+                       if (tmp -> next)
+                               interface_dereference (&tmp -> next, MDL);
 
                        /* Remember the interface in case we need to know
                           about it later. */
-                       tmp -> next = dummy_interfaces;
-                       dummy_interfaces = tmp;
+                       if (dummy_interfaces) {
+                               interface_reference (&tmp -> next,
+                                                    dummy_interfaces, MDL);
+                               interface_dereference (&dummy_interfaces, MDL);
+                       }
+                       interface_reference (&dummy_interfaces, tmp, MDL);
+                       interface_dereference (&tmp, MDL);
+                       if (next)
+                               interface_reference (&tmp, next, MDL);
                        continue;
                }
                last = tmp;
@@ -570,6 +523,9 @@ void discover_interfaces (state)
                                           tmp -> name);
                }
 #endif
+               interface_dereference (&tmp, MDL);
+               if (next)
+                       interface_reference (&tmp, next, MDL);
        }
 
        /* Now register all the remaining interfaces as protocols. */
@@ -577,8 +533,6 @@ void discover_interfaces (state)
                /* not if it's been registered before */
                if (tmp -> flags & INTERFACE_RUNNING)
                        continue;
-               tmp -> refcnt = 1;
-               tmp -> type = dhcp_type_interface;
                status = omapi_register_io_object ((omapi_object_t *)tmp,
                                                   if_readsocket, 0,
                                                   got_one, 0, 0);
@@ -617,21 +571,21 @@ int if_readsocket (h)
        return ip -> rfdesc;
 }
 
-struct interface_info *setup_fallback ()
+int setup_fallback (struct interface_info **fp, const char *file, int line)
 {
-       fallback_interface = ((struct interface_info *)
-                             dmalloc (sizeof *fallback_interface, MDL));
-       if (!fallback_interface)
-               log_fatal ("No memory to record fallback interface.");
-       memset (fallback_interface, 0, sizeof *fallback_interface);
+       isc_result_t status;
+
+       status = interface_allocate (&fallback_interface, file, line);
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Error allocating fallback interface: %s",
+                          isc_result_totext (status));
        strcpy (fallback_interface -> name, "fallback");
-       fallback_interface -> shared_network = new_shared_network (MDL);
-       if (!fallback_interface -> shared_network)
-               log_fatal ("No memory for shared subnet");
-       memset (fallback_interface -> shared_network, 0,
-               sizeof (struct shared_network));
-       fallback_interface -> shared_network -> name = "fallback-net";
-       return fallback_interface;
+       if (dhcp_interface_setup_hook)
+               (*dhcp_interface_setup_hook) (fallback_interface,
+                                             (struct iaddr *)0);
+       status = interface_reference (fp, fallback_interface, file, line);
+       interface_dereference (&fallback_interface, file, line);
+       return status == ISC_R_SUCCESS;
 }
 
 void reinitialize_interfaces ()
index 1ea4c80c22a3772123721334a991f07bb5147ff2..05a921047c18b7253959f7a75cbf69c79b2a0e68 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dispatch.c,v 1.61 2000/03/17 03:59:00 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dispatch.c,v 1.62 2000/05/16 23:02:14 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -78,6 +78,8 @@ void dispatch ()
                                t = timeouts;
                                timeouts = timeouts -> next;
                                (*(t -> func)) (t -> what);
+                               if (t -> unref)
+                                       (*t -> unref) (&t -> what, MDL);
                                t -> next = free_timeouts;
                                free_timeouts = t;
                                goto another;
@@ -95,10 +97,12 @@ void dispatch ()
                   isc_result_totext (status));
 }
 
-void add_timeout (when, where, what)
+void add_timeout (when, where, what, ref, unref)
        TIME when;
        void (*where) PROTO ((void *));
        void *what;
+       tvref_t ref;
+       tvunref_t unref;
 {
        struct timeout *t, *q;
 
@@ -122,16 +126,20 @@ void add_timeout (when, where, what)
                if (free_timeouts) {
                        q = free_timeouts;
                        free_timeouts = q -> next;
-                       q -> func = where;
-                       q -> what = what;
                } else {
                        q = ((struct timeout *)
                             dmalloc (sizeof (struct timeout), MDL));
                        if (!q)
                                log_fatal ("add_timeout: no memory!");
-                       q -> func = where;
-                       q -> what = what;
                }
+               memset (q, 0, sizeof *q);
+               q -> func = where;
+               q -> ref = ref;
+               q -> unref = unref;
+               if (q -> ref)
+                       (*q -> ref)(&q -> what, what, MDL);
+               else
+                       q -> what = what;
        }
 
        q -> when = when;
@@ -180,6 +188,8 @@ void cancel_timeout (where, what)
 
        /* If we found the timeout, put it on the free list. */
        if (q) {
+               if (q -> unref)
+                       (*q -> unref) (&q -> what, MDL);
                q -> next = free_timeouts;
                free_timeouts = q;
        }
index 8ea69dd4a0a8826d57f214f067cb799b0675cfa1..00b80296c61ce8dfbebd600570f908f462675417 100644 (file)
@@ -84,7 +84,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dlpi.c,v 1.19 2000/03/17 03:59:00 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dlpi.c,v 1.20 2000/05/16 23:02:15 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1306,12 +1306,9 @@ int can_receive_unicast_unconfigured (ip)
 void maybe_setup_fallback ()
 {
        isc_result_t status;
-       struct interface_info *fbi;
-       fbi = setup_fallback ();
-       if (fbi) {
+       struct interface_info *fbi = (struct interface_info *)0;
+       if (setup_fallback (&fbi, MDL)) {
                if_register_fallback (fbi);
-               fbi -> refcnt = 1;
-               fbi -> type = dhcp_type_interface;
                status = omapi_register_io_object ((omapi_object_t *)fbi,
                                                   if_readsocket, 0,
                                                   fallback_discard, 0, 0);
index cb1432099e83a41afe525fc980d58f91fd6d498f..b3ce2cf714917f76f102ef569f4b13d3247642b5 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dns.c,v 1.23 2000/05/03 23:04:43 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dns.c,v 1.24 2000/05/16 23:02:17 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -179,7 +179,6 @@ isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname,
        memcpy (tkey -> data,
                zone -> key -> key.data, zone -> key -> key.len);
        tkey -> len = zone -> key -> key.len;
-       *key = tkey;
        return ISC_R_SUCCESS;
 }
 
@@ -194,16 +193,20 @@ void tkey_free (ns_tsig_key **key)
 
 isc_result_t enter_dns_zone (struct dns_zone *zone)
 {
-       struct dns_zone *tz;
+       struct dns_zone *tz = (struct dns_zone *)0;
 
        if (dns_zone_hash) {
-               tz = hash_lookup (dns_zone_hash,
-                                 (unsigned char *)zone -> name, 0);
-               if (tz == zone)
+               dns_zone_hash_lookup (&tz,
+                                     dns_zone_hash, zone -> name, 0, MDL);
+               if (tz == zone) {
+                       dns_zone_dereference (&tz, MDL);
                        return ISC_R_SUCCESS;
-               if (tz)
-                       delete_hash_entry (dns_zone_hash,
-                                          (unsigned char *)zone -> name, 0);
+               }
+               if (tz) {
+                       dns_zone_hash_delete (dns_zone_hash,
+                                             zone -> name, 0, MDL);
+                       dns_zone_dereference (&tz, MDL);
+               }
        } else {
                dns_zone_hash =
                        new_hash ((hash_reference)dns_zone_reference,
@@ -211,15 +214,16 @@ isc_result_t enter_dns_zone (struct dns_zone *zone)
                if (!dns_zone_hash)
                        return ISC_R_NOMEMORY;
        }
-       add_hash (dns_zone_hash, (unsigned char *)zone -> name, 0, zone);
+       dns_zone_hash_add (dns_zone_hash, zone -> name, 0, zone, MDL);
        return ISC_R_SUCCESS;
 }
 
 isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name)
 {
-       struct dns_zone *tz;
+       struct dns_zone *tz = (struct dns_zone *)0;
        unsigned len;
        char *tname = (char *)0;
+       isc_result_t status;
 
        if (!dns_zone_hash)
                return ISC_R_NOTFOUND;
@@ -234,28 +238,32 @@ isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name)
                tname [len + 1] = 0;
                name = tname;
        }
-       tz = hash_lookup (dns_zone_hash, name, 0);
+       if (!dns_zone_hash_lookup (zone, dns_zone_hash, name, 0, MDL))
+               status = ISC_R_NOTFOUND;
+       else
+               status = ISC_R_SUCCESS;
+
        if (tname)
                dfree (tname, MDL);
-       if (!tz)
-               return ISC_R_NOTFOUND;
-       if (!dns_zone_reference (zone, tz, MDL))
-               return ISC_R_UNEXPECTED;
-       return ISC_R_SUCCESS;
+       return status;
 }
 
 isc_result_t enter_tsig_key (struct tsig_key *tkey)
 {
-       struct tsig_key *tk;
+       struct tsig_key *tk = (struct tsig_key *)0;
 
        if (tsig_key_hash) {
-               tk = hash_lookup (tsig_key_hash,
-                                 (unsigned char *)tkey -> name, 0);
-               if (tk == tkey)
+               tsig_key_hash_lookup (&tk, tsig_key_hash,
+                                     tkey -> name, 0, MDL);
+               if (tk == tkey) {
+                       tsig_key_dereference (&tk, MDL);
                        return ISC_R_SUCCESS;
-               if (tk)
-                       delete_hash_entry (tsig_key_hash,
-                                          (unsigned char *)tkey -> name, 0);
+               }
+               if (tk) {
+                       tsig_key_hash_delete (tsig_key_hash,
+                                             tkey -> name, 0, MDL);
+                       tsig_key_dereference (&tk, MDL);
+               }
        } else {
                tsig_key_hash =
                        new_hash ((hash_reference)tsig_key_reference,
@@ -263,7 +271,7 @@ isc_result_t enter_tsig_key (struct tsig_key *tkey)
                if (!tsig_key_hash)
                        return ISC_R_NOMEMORY;
        }
-       add_hash (tsig_key_hash, (unsigned char *)tkey -> name, 0, tkey);
+       tsig_key_hash_add (tsig_key_hash, tkey -> name, 0, tkey, MDL);
        return ISC_R_SUCCESS;
        
 }
@@ -273,11 +281,8 @@ isc_result_t tsig_key_lookup (struct tsig_key **tkey, const char *name) {
 
        if (!tsig_key_hash)
                return ISC_R_NOTFOUND;
-       tk = hash_lookup (tsig_key_hash, (const unsigned char *)name, 0);
-       if (!tk)
+       if (!tsig_key_hash_lookup (tkey, tsig_key_hash, name, 0, MDL))
                return ISC_R_NOTFOUND;
-       if (!tsig_key_reference (tkey, tk, MDL))
-               return ISC_R_UNEXPECTED;
        return ISC_R_SUCCESS;
 }
 
@@ -437,3 +442,6 @@ void repudiate_zone (struct dns_zone **zone)
        dns_zone_dereference (zone, MDL);
 }
 #endif /* NSUPDATE */
+
+HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone)
+HASH_FUNCTIONS (tsig_key, const char *, struct tsig_key)
index 87494ab9713af2d80df40ccc983bbae59d95fc7b..0b599feb2159187916b1626299349226d79bdffb 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: execute.c,v 1.31 2000/04/13 21:48:34 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: execute.c,v 1.32 2000/05/16 23:02:18 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -352,7 +352,7 @@ int execute_statements (packet, lease, in_options, out_options, scope,
                        break;
 
                      default:
-                       log_fatal ("bogus statement type %d\n", r -> op);
+                       log_fatal ("bogus statement type %d", r -> op);
                }
        }
 
index ffc9193ad19f52a51e80aa1bc852178ec1a08901..870f2e4de08831b1a630de3dc6d06d2583314848 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: hash.c,v 1.21 2000/04/20 00:56:20 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: hash.c,v 1.22 2000/05/16 23:02:19 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -119,11 +119,13 @@ static int do_hash (name, len, size)
        return accum % size;
 }
 
-void add_hash (table, name, len, pointer)
+void add_hash (table, name, len, pointer, file, line)
        struct hash_table *table;
        unsigned len;
        const unsigned char *name;
-       void *pointer;
+       hashed_object_t *pointer;
+       const char *file;
+       int line;
 {
        int hashno;
        struct hash_bucket *bp;
@@ -136,7 +138,7 @@ void add_hash (table, name, len, pointer)
                len = strlen ((const char *)name);
 
        hashno = (*table -> do_hash) (name, len, table -> hash_count);
-       bp = new_hash_bucket (MDL);
+       bp = new_hash_bucket (file, line);
 
        if (!bp) {
                log_error ("Can't add %s to hash table.", name);
@@ -145,7 +147,7 @@ void add_hash (table, name, len, pointer)
        bp -> name = name;
        if (table -> referencer) {
                foo = &bp -> value;
-               (*(table -> referencer)) (foo, pointer, MDL);
+               (*(table -> referencer)) (foo, pointer, file, line);
        } else
                bp -> value = pointer;
        bp -> next = table -> buckets [hashno];
@@ -153,10 +155,12 @@ void add_hash (table, name, len, pointer)
        table -> buckets [hashno] = bp;
 }
 
-void delete_hash_entry (table, name, len)
+void delete_hash_entry (table, name, len, file, line)
        struct hash_table *table;
        unsigned len;
        const unsigned char *name;
+       const char *file;
+       int line;
 {
        int hashno;
        struct hash_bucket *bp, *pbp = (struct hash_bucket *)0;
@@ -184,25 +188,28 @@ void delete_hash_entry (table, name, len)
                        }
                        if (table -> dereferencer) {
                                foo = &bp -> value;
-                               (*(table -> dereferencer)) (foo, MDL);
+                               (*(table -> dereferencer)) (foo, file, line);
                        }
-                       free_hash_bucket (bp, MDL);
+                       free_hash_bucket (bp, file, line);
                        break;
                }
                pbp = bp;       /* jwg, 9/6/96 - nice catch! */
        }
 }
 
-void *hash_lookup (table, name, len)
+int hash_lookup (vp, table, name, len, file, line)
+       hashed_object_t **vp;
        struct hash_table *table;
        const unsigned char *name;
        unsigned len;
+       const char *file;
+       int line;
 {
        int hashno;
        struct hash_bucket *bp;
 
        if (!table)
-               return (unsigned char *)0;
+               return 0;
        if (!len)
                len = strlen ((const char *)name);
 
@@ -210,10 +217,16 @@ void *hash_lookup (table, name, len)
 
        for (bp = table -> buckets [hashno]; bp; bp = bp -> next) {
                if (len == bp -> len
-                   && !(*table -> cmp) (bp -> name, name, len))
-                       return bp -> value;
+                   && !(*table -> cmp) (bp -> name, name, len)) {
+                       if (table -> referencer)
+                               (*table -> referencer) (vp, bp -> value,
+                                                       file, line);
+                       else
+                               *vp = bp -> value;
+                       return 1;
+               }
        }
-       return (unsigned char *)0;
+       return 0;
 }
 
 int casecmp (const void *v1, const void *v2, unsigned len)
@@ -242,3 +255,7 @@ int casecmp (const void *v1, const void *v2, unsigned len)
        }
        return 0;
 }
+
+HASH_FUNCTIONS (group, const char *, struct group_object)
+HASH_FUNCTIONS (universe, const char *, struct universe)
+HASH_FUNCTIONS (option, const char *, struct option)
index 86e974783ac3014922f8c8f8e9adff0e1ed2d0b9..de4a177d9bb2d222bae5be7d6387e5e60dc6482b 100644 (file)
@@ -44,7 +44,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: icmp.c,v 1.22 2000/03/17 03:59:01 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: icmp.c,v 1.23 2000/05/16 23:02:21 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -80,7 +80,8 @@ void icmp_startup (routep, handler)
                log_fatal ("attempted to reinitialize icmp protocol");
 
        result = omapi_object_type_register (&dhcp_type_icmp,
-                                            "icmp", 0, 0, 0, 0, 0, 0, 0, 0);
+                                            "icmp", 0, 0, 0, 0, 0, 0, 0, 0,
+                                            0, 0, sizeof (struct icmp_state));
 
        if (result != ISC_R_SUCCESS)
                log_fatal ("Can't register icmp object type: %s",
index aeeceba87f826265a4bde538932a3b32db095868..24b28ebd0b929e9df853f2b76edd55705c674d93 100644 (file)
@@ -37,7 +37,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: lpf.c,v 1.23 2000/03/17 03:59:01 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: lpf.c,v 1.24 2000/05/16 23:02:22 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -372,12 +372,9 @@ int can_receive_unicast_unconfigured (ip)
 void maybe_setup_fallback ()
 {
        isc_result_t status;
-       struct interface_info *fbi;
-       fbi = setup_fallback ();
-       if (fbi) {
+       struct interface_info *fbi = (struct interface_info *)0;
+       if (setup_fallback (&fbi, MDL)) {
                if_register_fallback (fbi);
-               fbi -> refcnt = 1;
-               fbi -> type = dhcp_type_interface;
                status = omapi_register_io_object ((omapi_object_t *)fbi,
                                                   if_readsocket, 0,
                                                   fallback_discard, 0, 0);
index 14bbc7a8174b4c25d801bb21c0cd83e112c046bb..ad78a9cd17434e3a7269b8d10ee890a7c2f124ad 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: memory.c,v 1.65 2000/03/17 03:59:01 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: memory.c,v 1.66 2000/05/16 23:02:23 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 
-struct group *clone_group (group, file, line)
-       struct group *group;
-       const char *file;
-       int line;
+struct group *root_group;
+struct hash_table *group_name_hash;
+int (*group_write_hook) (struct group_object *);
+
+isc_result_t delete_group (struct group_object *group, int writep)
 {
-       struct group *g = new_group (file, line);
-       if (!g)
-               log_fatal ("%s(%d): can't allocate new group", file, line);
-       *g = *group;
-       g -> statements = (struct executable_statement *)0;
-       g -> next = group;
-       return g;
+       struct group_object *d;
+
+       /* The group should exist and be hashed - if not, it's invalid. */
+       if (group_name_hash) {
+               d = (struct group_object *)0;
+               group_hash_lookup (&d, group_name_hash, group -> name,
+                                  strlen (group -> name), MDL);
+       } else
+               return ISC_R_INVALIDARG;
+       if (!d)
+               return ISC_R_INVALIDARG;
+
+       /* Also not okay to delete a group that's not the one in
+          the hash table. */
+       if (d != group)
+               return ISC_R_INVALIDARG;
+
+       /* If it's dynamic, and we're deleting it, we can just blow away the
+          hash table entry. */
+       if ((group -> flags & GROUP_OBJECT_DYNAMIC) &&
+           !(group -> flags & GROUP_OBJECT_STATIC)) {
+               group_hash_delete (group_name_hash,
+                                  group -> name, strlen (group -> name), MDL);
+       } else {
+               group -> flags |= GROUP_OBJECT_DELETED;
+               if (group -> group)
+                       group_dereference (&group -> group, MDL);
+       }
+
+       /* Store the group declaration in the lease file. */
+       if (writep && group_write_hook) {
+               if (!(*group_write_hook) (group))
+                       return ISC_R_IOERROR;
+       }
+       return ISC_R_SUCCESS;
 }
 
+isc_result_t supersede_group (struct group_object *group, int writep)
+{
+       struct group_object *t, *u;
+       isc_result_t status;
+
+       /* Register the group in the group name hash table,
+          so we can look it up later. */
+       if (group_name_hash) {
+               t = (struct group_object *)0;
+               group_hash_lookup (&t, group_name_hash,
+                       group -> name,
+                            strlen (group -> name), MDL);
+               if (t && t != group) {
+                       /* If this isn't a dynamic entry, then we need to flag
+                          the replacement as not dynamic either - otherwise,
+                          if the dynamic entry is deleted later, the static
+                          entry will come back next time the server is stopped
+                          and restarted. */
+                       if (!(t -> flags & GROUP_OBJECT_DYNAMIC))
+                               group -> flags |= GROUP_OBJECT_STATIC;
+
+                       /* Delete the old object if it hasn't already been
+                          deleted.  If it has already been deleted, get rid of
+                          the hash table entry.  This is a legitimate
+                          situation - a deleted static object needs to be kept
+                          around so we remember it's deleted. */
+                       if (!(t -> flags & GROUP_OBJECT_DELETED))
+                               delete_group (t, 0);
+                       else {
+                               group_hash_delete (group_name_hash,
+                                                  group -> name,
+                                                  strlen (group -> name),
+                                                  MDL);
+                               group_object_dereference (&t, MDL);
+                       }
+               }
+       } else {
+               group_name_hash = new_hash ((hash_reference)
+                                           group_object_reference,
+                                           (hash_dereference)
+                                           group_object_dereference, 0);
+               t = (struct group_object *)0;
+       }
+
+       /* Add the group to the group name hash if it's not
+          already there, and also thread it into the list of
+          dynamic groups if appropriate. */
+       if (!t) {
+               group_hash_add (group_name_hash, group -> name,
+                               strlen (group -> name), group, MDL);
+       }
+
+       /* Store the group declaration in the lease file. */
+       if (writep && group_write_hook) {
+               if (!(*group_write_hook) (group))
+                       return ISC_R_IOERROR;
+       }
+       return ISC_R_SUCCESS;
+}
+
+int clone_group (struct group **gp, struct group *group,
+                const char *file, int line)
+{
+       isc_result_t status;
+       struct group *g = (struct group *)0;
+
+       /* Normally gp should contain the null pointer, but for convenience
+          it's permissible to clone a group into itself. */
+       if (*gp && *gp != group)
+               return 0;
+       if (!group_allocate (&g, file, line))
+               return 0;
+       if (group == *gp)
+               *gp = (struct group *)0;
+       group_reference (gp, g, MDL);
+       g -> authoritative = group -> authoritative;
+       if (group -> shared_network) {
+               shared_network_reference (&g -> shared_network,
+                                         group -> shared_network, MDL);
+       }
+       group_reference (&g -> next, group, MDL);
+       group_dereference (&g, MDL);
+       return 1;
+}
index afe401330fc3a7ed8823ff4dadd64ec652104898..12b542878527023752811ecf1683b00380d88d75 100644 (file)
@@ -44,7 +44,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: nit.c,v 1.28 2000/03/17 03:59:01 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: nit.c,v 1.29 2000/05/16 23:02:24 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -410,12 +410,9 @@ int can_receive_unicast_unconfigured (ip)
 void maybe_setup_fallback ()
 {
        isc_result_t status;
-       struct interface_info *fbi;
-       fbi = setup_fallback ();
-       if (fbi) {
+       struct interface_info *fbi = (struct interface_info *)0;
+       if (setup_fallback (&fbi, MDL)) {
                if_register_fallback (fbi);
-               fbi -> refcnt = 1;
-               fbi -> type = dhcp_type_interface;
                status = omapi_register_io_object ((omapi_object_t *)fbi,
                                                   if_readsocket, 0,
                                                   fallback_discard, 0, 0);
index 559e3abd50f48f7651a8377a8d54f24769c085e5..309e9c916829afa784f560f2f61f61dc3f0038f3 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: options.c,v 1.58 2000/03/18 03:34:05 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: options.c,v 1.59 2000/05/16 23:02:27 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #define DHCP_OPTION_DATA
@@ -1192,8 +1192,9 @@ int option_space_encapsulate (result, packet, lease,
 {
        struct universe *u;
 
-       u = (struct universe *)hash_lookup (universe_hash,
-                                           name -> data, name -> len);
+       u = (struct universe *)0;
+       universe_hash_lookup (&u, universe_hash,
+                             name -> data, name -> len, MDL);
        if (!u) {
                log_error ("unknown option space %s.", name -> data);
                return 0;
@@ -1332,7 +1333,7 @@ void do_packet (interface, packet, len, from_port, from, hfrom)
        decoded_packet -> packet_length = len;
        decoded_packet -> client_port = from_port;
        decoded_packet -> client_addr = from;
-       decoded_packet -> interface = interface;
+       interface_reference (&decoded_packet -> interface, interface, MDL);
        decoded_packet -> haddr = hfrom;
        
        if (packet -> hlen > sizeof packet -> chaddr) {
index c3e19b9b8300de7f47687e66c0c2dad518290366..53557003403a20713b9dbb1c5398c41880d5fc08 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.72 2000/04/20 00:56:56 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.73 2000/05/16 23:02:28 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -799,12 +799,9 @@ struct option *parse_option_name (cfile, allocate, known)
 
                /* Look up the option name hash table for the specified
                   uname. */
-               universe = ((struct universe *)
-                           hash_lookup (universe_hash,
-                                        (unsigned char *)uname, 0));
-               /* If it's not there, we can't parse the rest of the
-                  declaration. */
-               if (!universe) {
+               universe = (struct universe *)0;
+               if (!universe_hash_lookup (&universe, universe_hash,
+                                          uname, 0, MDL)) {
                        parse_warn (cfile, "no option space named %s.", uname);
                        skip_to_semi (cfile);
                        return (struct option *)0;
@@ -817,8 +814,8 @@ struct option *parse_option_name (cfile, allocate, known)
        }
 
        /* Look up the actual option info... */
-       option = (struct option *)hash_lookup (universe -> hash,
-                                              (const unsigned char *)val, 0);
+       option = (struct option *)0;
+       option_hash_lookup (&option, universe -> hash, val, 0, MDL);
 
        /* If we didn't get an option structure, it's an undefined option. */
        if (option) {
@@ -913,8 +910,7 @@ void parse_option_space_decl (cfile)
        nu -> hash = new_hash (0, 0, 1);
        if (!nu -> hash)
                log_fatal ("Can't allocate %s option hash table.", nu -> name);
-       add_hash (universe_hash,
-                 (const unsigned char *)nu -> name, 0, (unsigned char *)nu);
+       universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
        parse_semi (cfile);
 }
 
@@ -1125,9 +1121,9 @@ int parse_option_code_definition (cfile, option)
                   XXX may start out static. */
        }
        option -> universe -> options [option -> code] = option;
-       add_hash (option -> universe -> hash,
-                 (const unsigned char *)option -> name,
-                 0, (unsigned char *)option);
+       option_hash_add (option -> universe -> hash,
+                        (const unsigned char *)option -> name,
+                        0, option, MDL);
        return 1;
 }
 
@@ -1349,9 +1345,11 @@ int parse_executable_statement (result, cfile, lose, case_context)
                        *lose = 1;
                        return 0;
                }
-               cta = find_class (val);
-               if (!cta) {
-                       parse_warn (cfile, "unknown class %s.", val);
+               cta = (struct class *)0;
+               status = find_class (&cta, val, MDL);
+               if (status != ISC_R_SUCCESS) {
+                       parse_warn (cfile, "class %s: %s",
+                                   val, isc_result_totext (status));
                        skip_to_semi (cfile);
                        *lose = 1;
                        return 0;
@@ -1697,9 +1695,9 @@ int parse_executable_statement (result, cfile, lose, case_context)
                        
              default:
                if (config_universe && is_identifier (token)) {
-                       option = ((struct option *)
-                                 hash_lookup (config_universe -> hash,
-                                              (const unsigned char *)val, 0));
+                       option = (struct option *)0;
+                       option_hash_lookup (&option, config_universe -> hash,
+                                           val, 0, MDL);
                        if (option) {
                                token = next_token (&val, cfile);
                                return parse_option_statement
index e574a21de8b3cb1b4a1be47fcaf00b03c95099e7..de851ac5cf0f407399ce51ae3925249c97613ec5 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tables.c,v 1.41 2000/04/08 01:15:46 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: tables.c,v 1.42 2000/05/16 23:02:30 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -888,9 +888,9 @@ void initialize_common_option_spaces()
                log_fatal ("Can't allocate dhcp option hash table.");
        for (i = 0; i < 256; i++) {
                dhcp_universe.options [i] = &dhcp_options [i];
-               add_hash (dhcp_universe.hash,
-                         (const unsigned char *)dhcp_options [i].name, 0,
-                         (unsigned char *)&dhcp_options [i]);
+               option_hash_add (dhcp_universe.hash,
+                                dhcp_options [i].name, 0,
+                                &dhcp_options [i], MDL);
        }
 
        /* Set up the Novell option universe (for option 63)... */
@@ -914,17 +914,17 @@ void initialize_common_option_spaces()
                log_fatal ("Can't allocate dhcp option hash table.");
        for (i = 0; i < 256; i++) {
                nwip_universe.options [i] = &dhcp_options [i];
-               add_hash (nwip_universe.hash,
-                         (const unsigned char *)dhcp_options [i].name, 0,
-                         (unsigned char *)&dhcp_options [i]);
+               option_hash_add (nwip_universe.hash,
+                                dhcp_options [i].name, 0,
+                                &dhcp_options [i], MDL);
        }
 
        /* Set up the hash of universes. */
        universe_hash = new_hash (0, 0, 1);
-       add_hash (universe_hash,
-                 (const unsigned char *)dhcp_universe.name, 0,
-                 (unsigned char *)&dhcp_universe);
-       add_hash (universe_hash,
-                 (const unsigned char *)nwip_universe.name, 0,
-                 (unsigned char *)&nwip_universe);
+       universe_hash_add (universe_hash,
+                          dhcp_universe.name, 0,
+                          &dhcp_universe, MDL);
+       universe_hash_add (universe_hash,
+                          nwip_universe.name, 0,
+                          &nwip_universe, MDL);
 }
index acbf56c8d4b363ad2553b7fcc1d73543702dc725..d590cbfdb6aaecad33012e98091bfe8ea17b5eac 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: upf.c,v 1.17 2000/03/17 03:59:02 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: upf.c,v 1.18 2000/05/16 23:02:31 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -356,12 +356,9 @@ int can_receive_unicast_unconfigured (ip)
 void maybe_setup_fallback ()
 {
        isc_result_t status;
-       struct interface_info *fbi;
-       fbi = setup_fallback ();
-       if (fbi) {
+       struct interface_info *fbi = (struct interface_info *)0;
+       if (setup_fallback (&fbi, MDL)) {
                if_register_fallback (fbi);
-               fbi -> refcnt = 1;
-               fbi -> type = dhcp_type_interface;
                status = omapi_register_io_object ((omapi_object_t *)fbi,
                                                   if_readsocket, 0,
                                                   fallback_discard, 0, 0);
index 638a9bfeb929dd9f4619035a8f09410428690b53..e80402c92c5105768c79b72d0d2004aa2185c6f1 100644 (file)
@@ -60,14 +60,18 @@ dhcpctl_status dhcpctl_initialize ()
                                    dhcpctl_callback_get_value,
                                    dhcpctl_callback_destroy,
                                    dhcpctl_callback_signal_handler,
-                                   dhcpctl_callback_stuff_values, 0, 0, 0);
+                                   dhcpctl_callback_stuff_values,
+                                   0, 0, 0, 0, 0,
+                                   sizeof (dhcpctl_callback_object_t));
        omapi_object_type_register (&dhcpctl_remote_type,
                                    "dhcpctl-remote",
                                    dhcpctl_remote_set_value,
                                    dhcpctl_remote_get_value,
                                    dhcpctl_remote_destroy,
                                    dhcpctl_remote_signal_handler,
-                                   dhcpctl_remote_stuff_values, 0, 0, 0);
+                                   dhcpctl_remote_stuff_values,
+                                   0, 0, 0, 0, 0,
+                                   sizeof (dhcpctl_remote_object_t));
        return ISC_R_SUCCESS;
 }
 
index 01c98fb6e338921c2b3dc027a43cc095e9ed6c8b..14515ec59774e40dfcea325eed762555a8dbbee3 100644 (file)
@@ -453,6 +453,7 @@ struct group_object {
 struct group {
        struct group *next;
 
+       int refcnt;
        struct group_object *object;
        struct subnet *subnet;
        struct shared_network *shared_network;
@@ -514,7 +515,7 @@ struct pool {
 struct shared_network {
        OMAPI_OBJECT_PREAMBLE;
        struct shared_network *next;
-       const char *name;
+       char *name;
        struct subnet *subnets;
        struct interface_info *interface;
        struct pool *pools;
@@ -944,7 +945,6 @@ int nwip_option_space_encapsulate PROTO ((struct data_string *,
 
 /* dhcpd.c */
 extern TIME cur_time;
-extern struct group root_group;
 
 extern const char *path_dhcpd_conf;
 extern const char *path_dhcpd_db;
@@ -956,6 +956,7 @@ int main PROTO ((int, char **, char **));
 void cleanup PROTO ((void));
 void lease_pinged PROTO ((struct iaddr, u_int8_t *, int));
 void lease_ping_timeout PROTO ((void *));
+int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia);
 
 /* conflex.c */
 isc_result_t new_parse PROTO ((struct parse **, int,
@@ -966,6 +967,7 @@ enum dhcp_token peek_token PROTO ((const char **, struct parse *));
 
 /* confpars.c */
 isc_result_t readconf PROTO ((void));
+isc_result_t parse_conf_file (const char *, struct group *, int);
 isc_result_t read_leases PROTO ((void));
 int parse_statement PROTO ((struct parse *,
                            struct group *, int, struct host_decl *, int));
@@ -980,15 +982,15 @@ void parse_pool_statement PROTO ((struct parse *, struct group *, int));
 int parse_boolean PROTO ((struct parse *));
 int parse_lbrace PROTO ((struct parse *));
 void parse_host_declaration PROTO ((struct parse *, struct group *));
-struct class *parse_class_declaration PROTO ((struct parse *,
-                                             struct group *, int));
+int parse_class_declaration PROTO ((struct class **, struct parse *,
+                                   struct group *, int));
 void parse_shared_net_declaration PROTO ((struct parse *, struct group *));
 void parse_subnet_declaration PROTO ((struct parse *,
                                      struct shared_network *));
 void parse_group_declaration PROTO ((struct parse *, struct group *));
 int parse_fixed_addr_param PROTO ((struct option_cache **, struct parse *));
 TIME parse_timestamp PROTO ((struct parse *));
-struct lease *parse_lease_declaration PROTO ((struct parse *));
+int parse_lease_declaration PROTO ((struct lease **, struct parse *));
 void parse_address_range PROTO ((struct parse *,
                                 struct group *, int, struct pool *));
 
@@ -1147,15 +1149,15 @@ void nak_lease PROTO ((struct packet *, struct iaddr *cip));
 void ack_lease PROTO ((struct packet *, struct lease *,
                       unsigned int, TIME, char *, int));
 void dhcp_reply PROTO ((struct lease *));
-struct lease *find_lease PROTO ((struct packet *,
-                                struct shared_network *, int *));
-struct lease *mockup_lease PROTO ((struct packet *,
-                                  struct shared_network *,
-                                  struct host_decl *));
+int find_lease PROTO ((struct lease **, struct packet *,
+                      struct shared_network *, int *, const char *, int));
+int mockup_lease PROTO ((struct lease **, struct packet *,
+                        struct shared_network *,
+                        struct host_decl *));
 void static_lease_dereference PROTO ((struct lease *, const char *, int));
 
-struct lease *allocate_lease PROTO ((struct packet *,
-                                    struct pool *, int, int *));
+int allocate_lease PROTO ((struct lease **, struct packet *,
+                          struct pool *, int *));
 int permitted PROTO ((struct packet *, struct permit *));
 int locate_network PROTO ((struct packet *));
 int parse_agent_information_option PROTO ((struct packet *, int, u_int8_t *));
@@ -1167,24 +1169,42 @@ unsigned cons_agent_information_options PROTO ((struct option_state *,
 void bootp PROTO ((struct packet *));
 
 /* memory.c */
-struct group *clone_group PROTO ((struct group *, const char *, int));
+int (*group_write_hook) (struct group_object *);
+extern struct group *root_group;
+extern struct hash_table *group_name_hash;
+isc_result_t delete_group (struct group_object *, int);
+isc_result_t supersede_group (struct group_object *, int);
+int clone_group (struct group **, struct group *, const char *, int);
+int write_group PROTO ((struct group_object *));
+
+/* salloc.c */
+struct lease *new_leases PROTO ((unsigned, const char *, int));
+OMAPI_OBJECT_ALLOC_DECL (lease, struct lease, dhcp_type_lease)
+OMAPI_OBJECT_ALLOC_DECL (class, struct class, dhcp_type_class)
+OMAPI_OBJECT_ALLOC_DECL (pool, struct pool, dhcp_type_pool)
+OMAPI_OBJECT_ALLOC_DECL (host, struct host_decl, dhcp_type_host);
 
 /* alloc.c */
+OMAPI_OBJECT_ALLOC_DECL (subnet, struct subnet, dhcp_type_subnet)
+OMAPI_OBJECT_ALLOC_DECL (shared_network, struct shared_network,
+                        dhcp_type_shared_network)
+OMAPI_OBJECT_ALLOC_DECL (group_object, struct group_object, dhcp_type_group)
+
+int group_allocate (struct group **, const char *, int);
+int group_reference (struct group **, struct group *, const char *, int);
+int group_dereference (struct group **, const char *, int);
 struct dhcp_packet *new_dhcp_packet PROTO ((const char *, int));
 struct hash_table *new_hash_table PROTO ((int, const char *, int));
 struct hash_bucket *new_hash_bucket PROTO ((const char *, int));
-struct lease *new_lease PROTO ((const char *, int));
-struct lease *new_leases PROTO ((unsigned, const char *, int));
-struct subnet *new_subnet PROTO ((const char *, int));
-struct class *new_class PROTO ((const char *, int));
-struct shared_network *new_shared_network PROTO ((const char *, int));
-struct group *new_group PROTO ((const char *, int));
 struct protocol *new_protocol PROTO ((const char *, int));
 struct lease_state *new_lease_state PROTO ((const char *, int));
 struct domain_search_list *new_domain_search_list PROTO ((const char *, int));
 struct name_server *new_name_server PROTO ((const char *, int));
 void free_name_server PROTO ((struct name_server *, const char *, int));
 struct option *new_option PROTO ((const char *, int));
+int group_allocate (struct group **, const char *, int);
+int group_reference (struct group **, struct group *, const char *, int);
+int group_dereference (struct group **, const char *, int);
 void free_option PROTO ((struct option *, const char *, int));
 struct universe *new_universe PROTO ((const char *, int));
 void free_universe PROTO ((struct universe *, const char *, int));
@@ -1192,18 +1212,11 @@ void free_domain_search_list PROTO ((struct domain_search_list *,
                                     const char *, int));
 void free_lease_state PROTO ((struct lease_state *, const char *, int));
 void free_protocol PROTO ((struct protocol *, const char *, int));
-void free_group PROTO ((struct group *, const char *, int));
-void free_shared_network PROTO ((struct shared_network *, const char *, int));
-void free_class PROTO ((struct class *, const char *, int));
-void free_subnet PROTO ((struct subnet *, const char *, int));
-void free_lease PROTO ((struct lease *, const char *, int));
 void free_hash_bucket PROTO ((struct hash_bucket *, const char *, int));
 void free_hash_table PROTO ((struct hash_table *, const char *, int));
 void free_dhcp_packet PROTO ((struct dhcp_packet *, const char *, int));
 struct client_lease *new_client_lease PROTO ((const char *, int));
 void free_client_lease PROTO ((struct client_lease *, const char *, int));
-struct pool *new_pool PROTO ((const char *, int));
-void free_pool PROTO ((struct pool *, const char *, int));
 struct auth_key *new_auth_key PROTO ((unsigned, const char *, int));
 void free_auth_key PROTO ((struct auth_key *, const char *, int));
 struct permit *new_permit PROTO ((const char *, int));
@@ -1463,6 +1476,9 @@ extern struct in_addr local_address;
 
 extern u_int16_t local_port;
 extern u_int16_t remote_port;
+extern int (*dhcp_interface_setup_hook) (struct interface_info *,
+                                        struct iaddr *);
+extern int (*dhcp_interface_discovery_hook) (struct interface_info *);
 
 extern void (*bootp_packet_handler) PROTO ((struct interface_info *,
                                            struct dhcp_packet *, unsigned,
@@ -1471,7 +1487,7 @@ extern void (*bootp_packet_handler) PROTO ((struct interface_info *,
 extern struct timeout *timeouts;
 extern omapi_object_type_t *dhcp_type_interface;
 void discover_interfaces PROTO ((int));
-struct interface_info *setup_fallback PROTO ((void));
+int setup_fallback (struct interface_info **, const char *, int);
 int if_readsocket PROTO ((omapi_object_t *));
 void reinitialize_interfaces PROTO ((void));
 void dispatch PROTO ((void));
@@ -1495,16 +1511,22 @@ struct protocol *add_protocol PROTO ((const char *, int,
                                      void *));
 
 void remove_protocol PROTO ((struct protocol *));
+OMAPI_OBJECT_ALLOC_DECL (interface,
+                        struct interface_info, dhcp_type_interface);
 
 /* hash.c */
 struct hash_table *new_hash PROTO ((hash_reference, hash_dereference, int));
 void add_hash PROTO ((struct hash_table *,
-                     const unsigned char *, unsigned, void *));
-void delete_hash_entry PROTO ((struct hash_table *,
-                              const unsigned char *, unsigned));
-void *hash_lookup PROTO ((struct hash_table *,
-                         const unsigned char *, unsigned));
+                     const unsigned char *, unsigned, hashed_object_t *,
+                     const char *, int));
+void delete_hash_entry PROTO ((struct hash_table *, const unsigned char *,
+                              unsigned, const char *, int));
+int hash_lookup PROTO ((hashed_object_t **, struct hash_table *,
+                       const unsigned char *, unsigned, const char *, int));
 int casecmp (const void *s, const void *t, unsigned len);
+HASH_FUNCTIONS_DECL (group, const char *, struct group_object)
+HASH_FUNCTIONS_DECL (universe, const char *, struct universe)
+HASH_FUNCTIONS_DECL (option, const char *, struct option)
 
 /* tables.c */
 extern struct universe dhcp_universe;
@@ -1610,11 +1632,12 @@ void go_daemon PROTO ((void));
 void write_client_pid_file PROTO ((void));
 void client_location_changed PROTO ((void));
 void do_release PROTO ((struct client_state *));
+int dhclient_interface_shutdown_hook (struct interface_info *);
+int dhclient_interface_discovery_hook (struct interface_info *);
 
 /* db.c */
 int write_lease PROTO ((struct lease *));
 int write_host PROTO ((struct host_decl *));
-int write_group PROTO ((struct group_object *));
 #if defined (FAILOVER_PROTOCOL)
 int write_failover_state (dhcp_failover_state_t *);
 #endif
@@ -1624,6 +1647,7 @@ int write_billing_class PROTO ((struct class *));
 int commit_leases PROTO ((void));
 void db_startup PROTO ((int));
 void new_lease_file PROTO ((void));
+int group_writer (struct group_object *);
 
 /* packet.c */
 u_int32_t checksum PROTO ((unsigned char *, unsigned, u_int32_t));
@@ -1700,7 +1724,7 @@ int parse_X PROTO ((struct parse *, u_int8_t *, unsigned));
 void parse_option_list PROTO ((struct parse *, u_int32_t **));
 void parse_interface_declaration PROTO ((struct parse *,
                                         struct client_config *, char *));
-struct interface_info *interface_or_dummy PROTO ((const char *));
+int interface_or_dummy PROTO ((struct interface_info **, const char *));
 void make_client_state PROTO ((struct client_state **));
 void make_client_config PROTO ((struct client_state *,
                                struct client_config *));
@@ -1750,6 +1774,8 @@ int find_cached_zone (const char *, ns_class, char *,
 void forget_zone (struct dns_zone **);
 void repudiate_zone (struct dns_zone **);
 #endif /* NSUPDATE */
+HASH_FUNCTIONS_DECL (dns_zone, const char *, struct dns_zone)
+HASH_FUNCTIONS_DECL (tsig_key, const char *, struct tsig_key)
 
 /* resolv.c */
 extern char path_resolv_conf [];
@@ -1777,7 +1803,8 @@ void classify_client PROTO ((struct packet *));
 int check_collection PROTO ((struct packet *, struct lease *,
                             struct collection *));
 void classify PROTO ((struct packet *, struct class *));
-struct class *find_class PROTO ((const char *));
+isc_result_t find_class PROTO ((struct class **, const char *,
+                               const char *, int));
 int unbill_class PROTO ((struct lease *, struct class *));
 int bill_class PROTO ((struct lease *, struct class *));
 
@@ -1808,13 +1835,78 @@ struct executable_statement *find_matching_case PROTO ((struct packet *,
 void enter_auth_key PROTO ((struct data_string *, struct auth_key *));
 const struct auth_key *auth_key_lookup PROTO ((struct data_string *));
 
-/* omapi.c */
+/* comapi.c */
 extern omapi_object_type_t *dhcp_type_interface;
-extern omapi_object_type_t *dhcp_type_lease;
 extern omapi_object_type_t *dhcp_type_group;
-extern omapi_object_type_t *dhcp_type_pool;
 extern omapi_object_type_t *dhcp_type_shared_network;
 extern omapi_object_type_t *dhcp_type_subnet;
+
+void dhcp_common_objects_setup (void);
+
+isc_result_t dhcp_group_set_value  (omapi_object_t *, omapi_object_t *,
+                                   omapi_data_string_t *,
+                                   omapi_typed_data_t *);
+isc_result_t dhcp_group_get_value (omapi_object_t *, omapi_object_t *,
+                                  omapi_data_string_t *,
+                                  omapi_value_t **); 
+isc_result_t dhcp_group_destroy (omapi_object_t *, const char *, int);
+isc_result_t dhcp_group_signal_handler (omapi_object_t *,
+                                       const char *, va_list);
+isc_result_t dhcp_group_stuff_values (omapi_object_t *,
+                                     omapi_object_t *,
+                                     omapi_object_t *);
+isc_result_t dhcp_group_lookup (omapi_object_t **,
+                               omapi_object_t *, omapi_object_t *);
+isc_result_t dhcp_group_create (omapi_object_t **,
+                               omapi_object_t *);
+isc_result_t dhcp_group_remove (omapi_object_t *,
+                               omapi_object_t *);
+
+isc_result_t dhcp_subnet_set_value  (omapi_object_t *, omapi_object_t *,
+                                    omapi_data_string_t *,
+                                    omapi_typed_data_t *);
+isc_result_t dhcp_subnet_get_value (omapi_object_t *, omapi_object_t *,
+                                   omapi_data_string_t *,
+                                   omapi_value_t **); 
+isc_result_t dhcp_subnet_destroy (omapi_object_t *, const char *, int);
+isc_result_t dhcp_subnet_signal_handler (omapi_object_t *,
+                                        const char *, va_list);
+isc_result_t dhcp_subnet_stuff_values (omapi_object_t *,
+                                      omapi_object_t *,
+                                      omapi_object_t *);
+isc_result_t dhcp_subnet_lookup (omapi_object_t **,
+                                omapi_object_t *, omapi_object_t *);
+isc_result_t dhcp_subnet_create (omapi_object_t **,
+                                omapi_object_t *);
+isc_result_t dhcp_subnet_remove (omapi_object_t *,
+                                omapi_object_t *);
+
+isc_result_t dhcp_shared_network_set_value  (omapi_object_t *,
+                                            omapi_object_t *,
+                                            omapi_data_string_t *,
+                                            omapi_typed_data_t *);
+isc_result_t dhcp_shared_network_get_value (omapi_object_t *,
+                                           omapi_object_t *,
+                                           omapi_data_string_t *,
+                                           omapi_value_t **); 
+isc_result_t dhcp_shared_network_destroy (omapi_object_t *, const char *, int);
+isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *,
+                                                const char *, va_list);
+isc_result_t dhcp_shared_network_stuff_values (omapi_object_t *,
+                                              omapi_object_t *,
+                                              omapi_object_t *);
+isc_result_t dhcp_shared_network_lookup (omapi_object_t **,
+                                        omapi_object_t *, omapi_object_t *);
+isc_result_t dhcp_shared_network_create (omapi_object_t **,
+                                        omapi_object_t *);
+isc_result_t dhcp_shared_network_remove (omapi_object_t *,
+                                        omapi_object_t *);
+
+/* omapi.c */
+extern int (*dhcp_interface_shutdown_hook) (struct interface_info *);
+
+extern omapi_object_type_t *dhcp_type_lease;
+extern omapi_object_type_t *dhcp_type_pool;
 extern omapi_object_type_t *dhcp_type_class;
 
 #if defined (FAILOVER_PROTOCOL)
@@ -1897,6 +1989,24 @@ isc_result_t dhcp_pool_create (omapi_object_t **,
                               omapi_object_t *);
 isc_result_t dhcp_pool_remove (omapi_object_t *,
                               omapi_object_t *);
+isc_result_t dhcp_class_set_value  (omapi_object_t *, omapi_object_t *,
+                                   omapi_data_string_t *,
+                                   omapi_typed_data_t *);
+isc_result_t dhcp_class_get_value (omapi_object_t *, omapi_object_t *,
+                                  omapi_data_string_t *,
+                                  omapi_value_t **); 
+isc_result_t dhcp_class_destroy (omapi_object_t *, const char *, int);
+isc_result_t dhcp_class_signal_handler (omapi_object_t *,
+                                       const char *, va_list);
+isc_result_t dhcp_class_stuff_values (omapi_object_t *,
+                                     omapi_object_t *,
+                                     omapi_object_t *);
+isc_result_t dhcp_class_lookup (omapi_object_t **,
+                               omapi_object_t *, omapi_object_t *);
+isc_result_t dhcp_class_create (omapi_object_t **,
+                               omapi_object_t *);
+isc_result_t dhcp_class_remove (omapi_object_t *,
+                               omapi_object_t *);
 isc_result_t dhcp_shared_network_set_value  (omapi_object_t *,
                                             omapi_object_t *,
                                             omapi_data_string_t *,
@@ -1946,6 +2056,29 @@ isc_result_t dhcp_class_lookup (omapi_object_t **,
                                omapi_object_t *, omapi_object_t *);
 isc_result_t dhcp_class_create (omapi_object_t **,
                                omapi_object_t *);
+isc_result_t dhcp_interface_set_value (omapi_object_t *,
+                                      omapi_object_t *,
+                                      omapi_data_string_t *,
+                                      omapi_typed_data_t *);
+isc_result_t dhcp_interface_get_value (omapi_object_t *,
+                                      omapi_object_t *,
+                                      omapi_data_string_t *,
+                                      omapi_value_t **);
+isc_result_t dhcp_interface_destroy (omapi_object_t *,
+                                    const char *, int);
+isc_result_t dhcp_interface_signal_handler (omapi_object_t *,
+                                           const char *,
+                                           va_list ap);
+isc_result_t dhcp_interface_stuff_values (omapi_object_t *,
+                                         omapi_object_t *,
+                                         omapi_object_t *);
+isc_result_t dhcp_interface_lookup (omapi_object_t **,
+                                   omapi_object_t *,
+                                   omapi_object_t *);
+isc_result_t dhcp_interface_create (omapi_object_t **,
+                                   omapi_object_t *);
+isc_result_t dhcp_interface_remove (omapi_object_t *,
+                                   omapi_object_t *);
 
 /* mdb.c */
 
@@ -1957,26 +2090,24 @@ extern struct hash_table *host_name_hash;
 extern struct hash_table *lease_uid_hash;
 extern struct hash_table *lease_ip_addr_hash;
 extern struct hash_table *lease_hw_addr_hash;
-extern struct hash_table *group_name_hash;
 
 extern omapi_object_type_t *dhcp_type_host;
 
-
 isc_result_t enter_host PROTO ((struct host_decl *, int, int));
 isc_result_t delete_host PROTO ((struct host_decl *, int));
-struct host_decl *find_hosts_by_haddr PROTO ((int, const unsigned char *,
-                                             unsigned));
-struct host_decl *find_hosts_by_uid PROTO ((const unsigned char *, unsigned));
-struct subnet *find_host_for_network PROTO ((struct host_decl **,
-                                            struct iaddr *,
-                                            struct shared_network *));
-isc_result_t delete_group (struct group_object *, int);
-isc_result_t supersede_group (struct group_object *, int);
+int find_hosts_by_haddr PROTO ((struct host_decl **, int,
+                               const unsigned char *, unsigned,
+                               const char *, int));
+int find_hosts_by_uid PROTO ((struct host_decl **, const unsigned char *,
+                             unsigned, const char *, int));
+int find_host_for_network PROTO ((struct subnet **, struct host_decl **,
+                                 struct iaddr *, struct shared_network *));
 void new_address_range PROTO ((struct iaddr, struct iaddr,
                               struct subnet *, struct pool *));
-extern struct subnet *find_grouped_subnet PROTO ((struct shared_network *,
-                                                 struct iaddr));
-extern struct subnet *find_subnet PROTO ((struct iaddr));
+isc_result_t dhcp_lease_free (omapi_object_t *, const char *, int);
+int find_grouped_subnet PROTO ((struct subnet **, struct shared_network *,
+                               struct iaddr, const char *, int));
+int find_subnet (struct subnet **, struct iaddr, const char *, int);
 void enter_shared_network PROTO ((struct shared_network *));
 void new_shared_network_interface PROTO ((struct parse *,
                                          struct shared_network *,
@@ -1985,13 +2116,17 @@ int subnet_inner_than PROTO ((struct subnet *, struct subnet *, int));
 void enter_subnet PROTO ((struct subnet *));
 void enter_lease PROTO ((struct lease *));
 int supersede_lease PROTO ((struct lease *, struct lease *, int, int));
+int lease_copy PROTO ((struct lease **, struct lease *, const char *, int));
 void release_lease PROTO ((struct lease *, struct packet *));
 void abandon_lease PROTO ((struct lease *, const char *));
 void dissociate_lease PROTO ((struct lease *));
 void pool_timer PROTO ((void *));
-struct lease *find_lease_by_uid PROTO ((const unsigned char *, unsigned));
-struct lease *find_lease_by_hw_addr PROTO ((const unsigned char *, unsigned));
-struct lease *find_lease_by_ip_addr PROTO ((struct iaddr));
+int find_lease_by_uid PROTO ((struct lease **, const unsigned char *,
+                             unsigned, const char *, int));
+int find_lease_by_hw_addr PROTO ((struct lease **, const unsigned char *,
+                                 unsigned, const char *, int));
+int find_lease_by_ip_addr PROTO ((struct lease **, struct iaddr,
+                                 const char *, int));
 void uid_hash_add PROTO ((struct lease *));
 void uid_hash_delete PROTO ((struct lease *));
 void hw_hash_add PROTO ((struct lease *));
@@ -1999,6 +2134,9 @@ void hw_hash_delete PROTO ((struct lease *));
 void write_leases PROTO ((void));
 void expire_all_pools PROTO ((void));
 void dump_subnets PROTO ((void));
+HASH_FUNCTIONS_DECL (lease, const unsigned char *, struct lease)
+HASH_FUNCTIONS_DECL (host, const unsigned char *, struct host_decl)
+HASH_FUNCTIONS_DECL (class, const char *, struct class)
 
 /* nsupdate.c */
 char *ddns_rev_name (struct lease *, struct lease_state *, struct packet *);
@@ -2021,7 +2159,7 @@ void dhcp_failover_startup PROTO ((void));
 void dhcp_failover_write_all_states (void);
 isc_result_t enter_failover_peer PROTO ((dhcp_failover_state_t *));
 isc_result_t find_failover_peer PROTO ((dhcp_failover_state_t **,
-                                       const char *));
+                                       const char *, const char *, int));
 isc_result_t dhcp_failover_link_initiate PROTO ((omapi_object_t *));
 isc_result_t dhcp_failover_link_signal PROTO ((omapi_object_t *,
                                               const char *, va_list));
@@ -2123,30 +2261,10 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *,
 void failover_print PROTO ((char *, unsigned *, unsigned, const char *));
 void update_partner PROTO ((struct lease *));
 int load_balance_mine (struct packet *, dhcp_failover_state_t *);
+OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_state, dhcp_failover_state_t,
+                        dhcp_type_failover_state)
+OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_listener, dhcp_failover_listener_t,
+                        dhcp_type_failover_listener)
+OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_link, dhcp_failover_link_t,
+                        dhcp_type_failover_listener)
 #endif /* FAILOVER_PROTOCOL */
-
-/* client/omapi.c */
-void dhclient_db_objects_setup PROTO ((void));
-isc_result_t dhclient_interface_set_value (omapi_object_t *,
-                                          omapi_object_t *,
-                                          omapi_data_string_t *,
-                                          omapi_typed_data_t *);
-isc_result_t dhclient_interface_get_value (omapi_object_t *,
-                                          omapi_object_t *,
-                                          omapi_data_string_t *,
-                                          omapi_value_t **);
-isc_result_t dhclient_interface_destroy (omapi_object_t *,
-                                              const char *, int);
-isc_result_t dhclient_interface_signal_handler (omapi_object_t *,
-                                               const char *,
-                                               va_list ap);
-isc_result_t dhclient_interface_stuff_values (omapi_object_t *,
-                                             omapi_object_t *,
-                                             omapi_object_t *);
-isc_result_t dhclient_interface_lookup (omapi_object_t **,
-                                       omapi_object_t *,
-                                       omapi_object_t *);
-isc_result_t dhclient_interface_create (omapi_object_t **,
-                                       omapi_object_t *);
-isc_result_t dhclient_interface_remove (omapi_object_t *,
-                                       omapi_object_t *);
index 41f86b229a01d9c2b6e00e0411dbd84661ddc249..3ed4751922bac27e2025b33bc06048a7e21b1fb5 100644 (file)
@@ -267,7 +267,8 @@ enum dhcp_token {
        POTENTIAL_CONFLICT_NIC = 465,
        STATE = 466,
        UNKNOWN_STATE = 567,
-       CLTT = 568
+       CLTT = 568,
+       INCLUDE = 569
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index 8617cdb3632cf237d4b9aad7b4c099a421f0b112..9105a210470ff55fac084f1f1472195c7f4b7ebc 100644 (file)
@@ -261,8 +261,8 @@ typedef struct _dhcp_failover_state {
        enum failover_state my_state;
        TIME my_stos;
 
-       omapi_object_t *link_to_peer;   /* Currently-established link
-                                          to peer. */
+       dhcp_failover_link_t *link_to_peer;     /* Currently-established link
+                                                  to peer. */
 
        enum {
                primary, secondary
index 5ad37c11bee2034ef3f0e507327607721f5e31e5..e780ce1d840dfebed6a6ad70faec28f37ca9c36a 100644 (file)
 
 #define DEFAULT_HASH_SIZE      97
 
-typedef int (*hash_reference) (void *, void *, const char *, int);
-typedef int (*hash_dereference) (void *, const char *, int);
+/* The purpose of the hashed_object_t struct is to not match anything else. */
+typedef struct {
+       int foo;
+} hashed_object_t;
+
+typedef int (*hash_reference) (hashed_object_t **, hashed_object_t *,
+                              const char *, int);
+typedef int (*hash_dereference) (hashed_object_t **, const char *, int);
 
 struct hash_bucket {
        struct hash_bucket *next;
        const unsigned char *name;
        unsigned len;
-       void *value;
+       hashed_object_t *value;
 };
 
 typedef int (*hash_comparator_t)(const void *, const void *, size_t);
@@ -69,3 +75,37 @@ struct named_hash {
        const char *name;
        struct hash_table *hash;
 };
+
+#define HASH_FUNCTIONS_DECL(name, bufarg, type)                                      \
+void name##_hash_add (struct hash_table *, bufarg, unsigned, type *,         \
+                     const char *, int);                                     \
+void name##_hash_delete (struct hash_table *, bufarg, unsigned,                      \
+                        const char *, int);                                  \
+int name##_hash_lookup (type **, struct hash_table *, bufarg, unsigned,              \
+                       const char *, int);
+
+#define HASH_FUNCTIONS(name, bufarg, type)                                   \
+void name##_hash_add (struct hash_table *table,                                      \
+                     bufarg buf, unsigned len, type *ptr,                    \
+                     const char *file, int line)                             \
+{                                                                            \
+       add_hash (table,                                                      \
+                 (const unsigned char *)buf,                                 \
+                 len, (hashed_object_t *)ptr, file, line);                   \
+}                                                                            \
+                                                                             \
+void name##_hash_delete (struct hash_table *table,                           \
+                        bufarg buf, unsigned len, const char *file, int line)\
+{                                                                            \
+       delete_hash_entry (table, (const unsigned char *)buf,                 \
+                          len, file, line);                                  \
+}                                                                            \
+                                                                             \
+int name##_hash_lookup (type **ptr, struct hash_table *table,                \
+                       bufarg buf, unsigned len, const char *file, int line) \
+{                                                                            \
+       return hash_lookup ((hashed_object_t **)ptr, table,                   \
+                           (const unsigned char *)buf, len, file, line);     \
+}
+
+                           
index bc48f181d1380279d42966009b035e4ba79d728b..289bb2734d3c0a25e5d0d05e4aeb2dc0ef7c1dac 100644 (file)
@@ -121,6 +121,9 @@ typedef struct __omapi_object_type_t {
                                omapi_object_t *);
        isc_result_t (*create) (omapi_object_t **, omapi_object_t *);
        isc_result_t (*remove) (omapi_object_t *, omapi_object_t *);
+       isc_result_t (*freer) (omapi_object_t *, const char *, int);
+       isc_result_t (*sizer) (size_t);
+       size_t size;
 } omapi_object_type_t;
 
 #define OMAPI_OBJECT_PREAMBLE \
@@ -150,6 +153,31 @@ typedef struct {
        omapi_addr_t *addresses;
 } omapi_addr_list_t;
 
+#define OMAPI_OBJECT_ALLOC(name, stype, type) \
+isc_result_t name##_allocate (stype **p, const char *file, int line)         \
+{                                                                            \
+       return omapi_object_allocate ((omapi_object_t **)p,                   \
+                                     type, 0, file, line);                   \
+}                                                                            \
+                                                                             \
+isc_result_t name##_reference (stype **pptr, stype *ptr,                     \
+                              const char *file, int line)                    \
+{                                                                            \
+       return omapi_object_reference ((omapi_object_t **)pptr,               \
+                                      (omapi_object_t *)ptr, file, line);    \
+}                                                                            \
+                                                                             \
+isc_result_t name##_dereference (stype **ptr, const char *file, int line)     \
+{                                                                            \
+       return omapi_object_dereference ((omapi_object_t **)ptr, file, line); \
+}
+
+#define OMAPI_OBJECT_ALLOC_DECL(name, stype, type) \
+isc_result_t name##_allocate (stype **p, const char *file, int line); \
+isc_result_t name##_reference (stype **pptr, stype *ptr, \
+                              const char *file, int line); \
+isc_result_t name##_dereference (stype **ptr, const char *file, int line);
+
 isc_result_t omapi_protocol_connect (omapi_object_t *,
                                     const char *, unsigned, omapi_object_t *);
 isc_result_t omapi_connect_list (omapi_object_t *, omapi_addr_list_t *,
@@ -222,7 +250,6 @@ isc_result_t omapi_connection_put_string (omapi_object_t *, const char *);
 isc_result_t omapi_connection_put_handle (omapi_object_t *c,
                                          omapi_object_t *h);
 
-
 isc_result_t omapi_listen (omapi_object_t *, unsigned, int);
 isc_result_t omapi_listen_addr (omapi_object_t *,
                                omapi_addr_t *, int);
@@ -335,7 +362,10 @@ isc_result_t omapi_object_type_register (omapi_object_type_t **,
                                         isc_result_t (*) (omapi_object_t **,
                                                           omapi_object_t *),
                                         isc_result_t (*) (omapi_object_t *,
-                                                          omapi_object_t *));
+                                                          omapi_object_t *),
+                                        isc_result_t (*) (omapi_object_t *,
+                                                          const char *, int),
+                                        isc_result_t (*) (size_t), size_t);
 isc_result_t omapi_signal (omapi_object_t *, const char *, ...);
 isc_result_t omapi_signal_in (omapi_object_t *, const char *, ...);
 isc_result_t omapi_set_value (omapi_object_t *, omapi_object_t *,
@@ -385,6 +415,24 @@ isc_result_t omapi_object_handle (omapi_handle_t *, omapi_object_t *);
 isc_result_t omapi_handle_lookup (omapi_object_t **, omapi_handle_t);
 isc_result_t omapi_handle_td_lookup (omapi_object_t **, omapi_typed_data_t *);
 
+void * dmalloc (unsigned, const char *, int);
+void dfree (void *, const char *, int);
+#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL)
+void dmalloc_reuse (void *, const char *, int, int);
+void dmalloc_dump_outstanding (void);
+#else
+#define dmalloc_reuse(x,y,l,z)
+#endif
+#define MDL __FILE__, __LINE__
+#if defined (DEBUG_RC_HISTORY)
+void dump_rc_history (void);
+#endif
+isc_result_t omapi_object_allocate (omapi_object_t **,
+                                   omapi_object_type_t *,
+                                   size_t, const char *, int);
+isc_result_t omapi_object_initialize (omapi_object_t *,
+                                     omapi_object_type_t *,
+                                     size_t, size_t, const char *, int);
 isc_result_t omapi_object_reference (omapi_object_t **,
                                     omapi_object_t *, const char *, int);
 isc_result_t omapi_object_dereference (omapi_object_t **, const char *, int);
@@ -414,16 +462,4 @@ isc_result_t omapi_addr_list_reference (omapi_addr_list_t **,
 isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **,
                                          const char *, int);
 
-void * dmalloc (unsigned, const char *, int);
-void dfree (void *, const char *, int);
-#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL)
-void dmalloc_reuse (void *, const char *, int, int);
-void dmalloc_dump_outstanding (void);
-#else
-#define dmalloc_reuse(x,y,l,z)
-#endif
-#define MDL __FILE__, __LINE__
-#if defined (DEBUG_RC_HISTORY)
-void dump_rc_history (void);
-#endif
 #endif /* _OMAPIP_H_ */
index 5fd64cf4a2ff570309c2fd6597bcf7efd9431db2..cb9b995eade1033d7d04c27c50efdf5eeed3c548 100644 (file)
@@ -3,7 +3,7 @@
    Private master include file for the OMAPI library. */
 
 /*
- * Copyright (c) 1996-1999 Internet Software Consortium.
+ * Copyright (c) 1996-2000 Internet Software Consortium.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -146,6 +146,12 @@ typedef struct {
 
 #include <omapip/buffer.h>
 
+typedef struct __omapi_listener_object {
+       OMAPI_OBJECT_PREAMBLE;
+       int socket;             /* Connection socket. */
+       struct sockaddr_in address;
+} omapi_listener_object_t;
+
 typedef struct __omapi_connection_object {
        OMAPI_OBJECT_PREAMBLE;
        int socket;             /* Connection socket. */
@@ -160,16 +166,10 @@ typedef struct __omapi_connection_object {
        omapi_buffer_t *inbufs;
        u_int32_t out_bytes;    /* Bytes of output in buffers. */
        omapi_buffer_t *outbufs;
-       omapi_object_t *listener;       /* Listener that accepted this
-                                          connection, if any. */
+       omapi_listener_object_t *listener;      /* Listener that accepted this
+                                                  connection, if any. */
 } omapi_connection_object_t;
 
-typedef struct __omapi_listener_object {
-       OMAPI_OBJECT_PREAMBLE;
-       int socket;             /* Connection socket. */
-       struct sockaddr_in address;
-} omapi_listener_object_t;
-
 typedef struct __omapi_io_object {
        OMAPI_OBJECT_PREAMBLE;
        struct __omapi_io_object *next;
@@ -206,6 +206,24 @@ typedef struct __omapi_handle_table {
 
 #include <omapip/alloc.h>
 
+OMAPI_OBJECT_ALLOC_DECL (omapi_protocol, omapi_protocol_object_t,
+                        omapi_type_protocol)
+OMAPI_OBJECT_ALLOC_DECL (omapi_protocol_listener,
+                        omapi_protocol_listener_object_t,
+                        omapi_type_protocol_listener)
+OMAPI_OBJECT_ALLOC_DECL (omapi_connection,
+                        omapi_connection_object_t, omapi_type_connection)
+OMAPI_OBJECT_ALLOC_DECL (omapi_listener,
+                        omapi_listener_object_t, omapi_type_listener)
+OMAPI_OBJECT_ALLOC_DECL (omapi_io,
+                        omapi_io_object_t, omapi_type_io_object)
+OMAPI_OBJECT_ALLOC_DECL (omapi_waiter,
+                        omapi_waiter_object_t, omapi_type_waiter)
+OMAPI_OBJECT_ALLOC_DECL (omapi_generic,
+                        omapi_generic_object_t, omapi_type_generic)
+OMAPI_OBJECT_ALLOC_DECL (omapi_message,
+                        omapi_message_object_t, omapi_type_message)
+
 extern int log_priority;
 extern int log_perror;
 extern void (*log_cleanup) (void);
index 05f4a196b9209c492e28153c89241a39f39ac37f..88b1149110439194a025a9729b978e50a263bea7 100644 (file)
@@ -309,6 +309,47 @@ void dump_rc_history ()
 }
 #endif
 
+isc_result_t omapi_object_allocate (omapi_object_t **o,
+                                   omapi_object_type_t *type,
+                                   size_t size,
+                                   const char *file, int line)
+{
+       size_t tsize;
+       void *foo;
+       isc_result_t status;
+
+       if (type -> sizer)
+               tsize = (*type -> sizer) (size);
+       else
+               tsize = type -> size;
+
+       /* Sanity check. */
+       if (tsize < sizeof (omapi_object_t))
+               return ISC_R_INVALIDARG;
+
+       foo = dmalloc (tsize, file, line);
+       if (!foo)
+               return ISC_R_NOMEMORY;
+
+       status = omapi_object_initialize ((omapi_object_t *)foo,
+                                         type, size, tsize, file, line);
+       if (status != ISC_R_SUCCESS) {
+               dfree (foo, file, line);
+               return status;
+       }
+       return omapi_object_reference (o, (omapi_object_t *)foo, file, line);
+}
+
+isc_result_t omapi_object_initialize (omapi_object_t *o,
+                                     omapi_object_type_t *type,
+                                     size_t usize, size_t psize,
+                                     const char *file, int line)
+{
+       memset (o, 0, psize);
+       o -> type = type;
+       return ISC_R_SUCCESS;
+}
+
 isc_result_t omapi_object_reference (omapi_object_t **r,
                                     omapi_object_t *h,
                                     const char *file, int line)
index 194d30ee0ed5b4c16a42f724ec1efebebcfea985..cdeeeb2bc663bfdf16f88c2ab1e93b06d7781040 100644 (file)
@@ -44,6 +44,9 @@
 #include <omapip/omapip_p.h>
 #include <arpa/inet.h>
 
+OMAPI_OBJECT_ALLOC (omapi_connection,
+                   omapi_connection_object_t, omapi_type_connection)
+
 isc_result_t omapi_connect (omapi_object_t *c,
                            const char *server_name,
                            unsigned port)
@@ -66,8 +69,9 @@ isc_result_t omapi_connect (omapi_object_t *c,
                        return ISC_R_HOSTUNKNOWN;
                hix = i;
 
-               if (!omapi_addr_list_new (&addrs, hix, MDL))
-                       return ISC_R_NOMEMORY;
+               status = omapi_addr_list_new (&addrs, hix, MDL);
+               if (status != ISC_R_SUCCESS)
+                       return status;
                for (i = 0; i < hix; i++) {
                        addrs -> addresses [i].addrtype = he -> h_addrtype;
                        addrs -> addresses [i].addrlen = he -> h_length;
@@ -77,8 +81,9 @@ isc_result_t omapi_connect (omapi_object_t *c,
                        addrs -> addresses [i].port = port;
                }
        } else {
-               if (!omapi_addr_list_new (&addrs, 1, MDL))
-                       return ISC_R_NOMEMORY;
+               status = omapi_addr_list_new (&addrs, 1, MDL);
+               if (status != ISC_R_SUCCESS)
+                       return status;
                addrs -> addresses [0].addrtype = AF_INET;
                addrs -> addresses [0].addrlen = sizeof foo;
                memcpy (addrs -> addresses [0].address, &foo, sizeof foo);
@@ -99,23 +104,20 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
        int flag;
        struct sockaddr_in local_sin;
 
-       obj = (omapi_connection_object_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       rc_register_mdl (&obj, obj, obj -> refcnt);
-       obj -> type = omapi_type_connection;
+       obj = (omapi_connection_object_t *)0;
+       status = omapi_connection_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        status = omapi_object_reference (&c -> outer, (omapi_object_t *)obj,
                                         MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&obj -> inner, c, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                return status;
        }
 
@@ -123,7 +125,7 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
        obj -> socket =
                socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (obj -> socket < 0) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
                        return ISC_R_NORESOURCES;
                return ISC_R_UNEXPECTED;
@@ -133,8 +135,7 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
        if (local_addr) {
                /* Only do TCPv4 so far. */
                if (local_addr -> addrtype != AF_INET) {
-                       omapi_object_dereference ((omapi_object_t **)&obj,
-                                                 MDL);
+                       omapi_connection_dereference (&obj, MDL);
                        return ISC_R_INVALIDARG;
                }
                local_sin.sin_port = htons (local_addr -> port);
@@ -164,7 +165,7 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
 #if defined (HAVE_SETFD)
        if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
                close (obj -> socket);
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
 #endif
@@ -173,13 +174,13 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
        flag = 1;
        if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR,
                        (char *)&flag, sizeof flag) < 0) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
        
        /* Set the file to nonblocking mode. */
        if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
 
@@ -195,7 +196,7 @@ isc_result_t omapi_connect_list (omapi_object_t *c,
 
        obj -> state = omapi_connection_unconnected;
        omapi_connection_connect ((omapi_object_t *)obj);
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+       omapi_connection_dereference (&obj, MDL);
        return status;
 }
 
@@ -441,7 +442,7 @@ isc_result_t omapi_connection_destroy (omapi_object_t *h,
        if (c -> state == omapi_connection_connected)
                omapi_disconnect (h, 1);
        if (c -> listener)
-               omapi_object_dereference (&c -> listener, file, line);
+               omapi_listener_dereference (&c -> listener, file, line);
        if (c -> connect_list)
                omapi_addr_list_dereference (&c -> connect_list, file, line);
        return ISC_R_SUCCESS;
index 46e5fa4d82748723002b7f6e0f812b1b66e12f57..ceecbe144309935e6ed706c90dd29285d4641cf8 100644 (file)
 static omapi_io_object_t omapi_io_states;
 u_int32_t cur_time;
 
+OMAPI_OBJECT_ALLOC (omapi_io,
+                   omapi_io_object_t, omapi_type_io_object)
+OMAPI_OBJECT_ALLOC (omapi_waiter,
+                   omapi_waiter_object_t, omapi_type_waiter)
+
 /* Register an I/O handle so that we can do asynchronous I/O on it. */
 
 isc_result_t omapi_register_io_object (omapi_object_t *h,
@@ -71,24 +76,21 @@ isc_result_t omapi_register_io_object (omapi_object_t *h,
                omapi_io_states.type = omapi_type_io_object;
        }
                
-       obj = dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       rc_register_mdl (&obj, obj, obj -> refcnt);
-       obj -> type = omapi_type_io_object;
+       obj = (omapi_io_object_t *)0;
+       status = omapi_io_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        status = omapi_object_reference (&obj -> inner, h, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_io_dereference (&obj, MDL);
                return status;
        }
 
        status = omapi_object_reference (&h -> outer,
                                         (omapi_object_t *)obj, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_io_dereference (&obj, MDL);
                return status;
        }
 
@@ -97,12 +99,9 @@ isc_result_t omapi_register_io_object (omapi_object_t *h,
             p && p -> next; p = p -> next)
                ;
        if (p)
-               omapi_object_reference ((omapi_object_t **)&p -> next,
-                                       (omapi_object_t *)obj, MDL);
+               omapi_io_reference (&p -> next, obj, MDL);
        else
-               omapi_object_reference
-                       ((omapi_object_t **)&omapi_io_states.next,
-                        (omapi_object_t *)obj, MDL);
+               omapi_io_reference (&omapi_io_states.next, obj, MDL);
 
        obj -> readfd = readfd;
        obj -> writefd = writefd;
@@ -114,29 +113,26 @@ isc_result_t omapi_register_io_object (omapi_object_t *h,
 
 isc_result_t omapi_unregister_io_object (omapi_object_t *h)
 {
-       omapi_io_object_t *p, *obj, *last;
-       omapi_object_t *ph;
+       omapi_io_object_t *p, *obj, *last, *ph;
 
+       if (!h -> outer || h -> outer -> type != omapi_type_io_object)
+               return ISC_R_INVALIDARG;
        obj = (omapi_io_object_t *)h -> outer;
-       ph = (omapi_object_t *)0;
-       omapi_object_reference (&ph, h -> outer, MDL);
+       ph = (omapi_io_object_t *)0;
+       omapi_io_reference (&ph, obj, MDL);
 
        /* remove from the list of I/O states */
        for (p = omapi_io_states.next; p; p = p -> next) {
-               if ((omapi_object_t *)p == h -> outer) {
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &last -> next, MDL);
-                       omapi_object_reference ((omapi_object_t **)
-                                               &last -> next,
-                                               (omapi_object_t *)p -> next,
-                                               MDL);
+               if (p == obj) {
+                       omapi_io_dereference (&last -> next, MDL);
+                       omapi_io_reference (&last -> next, p -> next, MDL);
                        break;
                }
                last = p;
        }
        if (obj -> next)
-               omapi_object_dereference ((omapi_object_t **)&obj -> next,
-                                         MDL);
+               omapi_io_dereference (&obj -> next, MDL);
+
        if (obj -> outer) {
                if (obj -> outer -> inner == (omapi_object_t *)obj)
                        omapi_object_dereference (&obj -> outer -> inner,
@@ -145,7 +141,7 @@ isc_result_t omapi_unregister_io_object (omapi_object_t *h)
        }
        omapi_object_dereference (&obj -> inner, MDL);
        omapi_object_dereference (&h -> outer, MDL);
-       omapi_object_dereference (&ph, MDL);
+       omapi_io_dereference (&ph, MDL);
        return ISC_R_SUCCESS;
 }
 
@@ -163,13 +159,10 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
        omapi_object_t *inner;
 
        if (object) {
-               waiter = dmalloc (sizeof *waiter, MDL);
-               if (!waiter)
-                       return ISC_R_NOMEMORY;
-               memset (waiter, 0, sizeof *waiter);
-               waiter -> refcnt = 1;
-               rc_register_mdl (&waiter, waiter, waiter -> refcnt);
-               waiter -> type = omapi_type_waiter;
+               waiter = (omapi_waiter_object_t *)0;
+               status = omapi_waiter_allocate (&waiter, MDL);
+               if (status != ISC_R_SUCCESS)
+                       return status;
 
                /* Paste the waiter object onto the inner object we're
                   waiting on. */
@@ -178,8 +171,7 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
 
                status = omapi_object_reference (&waiter -> outer, inner, MDL);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference ((omapi_object_t **)&waiter,
-                                                 MDL);
+                       omapi_waiter_dereference (&waiter, MDL);
                        return status;
                }
                
@@ -187,8 +179,7 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
                                                 (omapi_object_t *)waiter,
                                                 MDL);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference ((omapi_object_t **)&waiter,
-                                                 MDL);
+                       omapi_waiter_dereference (&waiter, MDL);
                        return status;
                }
        } else
@@ -214,7 +205,7 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
        if (waiter -> inner)
                omapi_object_dereference (&waiter -> inner, MDL);
        
-       omapi_object_dereference ((omapi_object_t **)&waiter, MDL);
+       omapi_waiter_dereference (&waiter, MDL);
        return ISC_R_SUCCESS;
 }
 
@@ -334,31 +325,22 @@ isc_result_t omapi_one_dispatch (omapi_object_t *wo,
                                /* Save a reference to the next
                                   pointer, if there is one. */
                                if (io -> next)
-                                       omapi_object_reference
-                                               ((omapi_object_t **)&tmp,
-                                                (omapi_object_t *)io -> next,
-                                                MDL);
+                                       omapi_io_reference (&tmp,
+                                                           io -> next, MDL);
                                if (prev) {
-                                       omapi_object_dereference
-                                               (((omapi_object_t **)
-                                                 &prev -> next), MDL);
+                                       omapi_io_dereference (&prev -> next,
+                                                             MDL);
                                        if (tmp)
-                                               omapi_object_reference
-                                                   (((omapi_object_t **)
-                                                     &prev -> next),
-                                                    (omapi_object_t *)tmp,
-                                                    MDL);
+                                               omapi_io_reference
+                                                       (&prev -> next,
+                                                        tmp, MDL);
                                } else {
-                                       omapi_object_dereference
-                                               (((omapi_object_t **)
-                                                 &omapi_io_states.next),
-                                                MDL);
+                                       omapi_io_dereference
+                                               (&omapi_io_states.next, MDL);
                                        if (tmp)
-                                               omapi_object_reference
-                                                   (((omapi_object_t **)
-                                                     &omapi_io_states.next),
-                                                    (omapi_object_t *)tmp,
-                                                    MDL);
+                                               omapi_io_reference
+                                                   (&omapi_io_states.next,
+                                                    tmp, MDL);
                                        else
                                                omapi_signal_in
                                                        ((omapi_object_t *)
@@ -366,8 +348,7 @@ isc_result_t omapi_one_dispatch (omapi_object_t *wo,
                                                         "ready");
                                }
                                if (tmp)
-                                       omapi_object_dereference
-                                               ((omapi_object_t **)&tmp, MDL);
+                                       omapi_io_dereference (&tmp, MDL);
                        }
                }
                prev = io;
@@ -416,13 +397,9 @@ isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
        /* remove from the list of I/O states */
        for (p = omapi_io_states.next; p; p = p -> next) {
                if (p == obj) {
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &last -> next, MDL);
-                       omapi_object_reference ((omapi_object_t **)
-                                               &last -> next,
-                                               (omapi_object_t *)p -> next,
-                                               MDL);
-                       omapi_object_dereference ((omapi_object_t **)&p, MDL);
+                       omapi_io_dereference (&last -> next, MDL);
+                       omapi_io_reference (&last -> next, p -> next, MDL);
+                       omapi_io_dereference (&p, MDL);
                        break;
                }
                last = p;
index 9832e855c3927a41010d0736891569fb5b1c03f9..a056798f9b9646b02067ee20d8d47772e2d5a2a9 100644 (file)
 
 #include <omapip/omapip_p.h>
 
+OMAPI_OBJECT_ALLOC (omapi_generic,
+                   omapi_generic_object_t, omapi_type_generic)
+
 isc_result_t omapi_generic_new (omapi_object_t **gen,
                                const char *file, int line)
 {
-       omapi_generic_object_t *obj;
-
-       obj = dmalloc (sizeof *obj, file, line);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 0;
-       obj -> type = omapi_type_generic;
-
-       return omapi_object_reference (gen, (omapi_object_t *)obj, file, line);
+       /* Backwards compatibility. */
+       return omapi_generic_allocate ((omapi_generic_object_t **)gen,
+                                      file, line);
 }
 
 isc_result_t omapi_generic_set_value (omapi_object_t *h,
index e059567c5e29f0725c610553363fcb3225b7cb59..23c6250f7ec096e7d5564f1f2938ac662dda8ab2 100644 (file)
@@ -43,6 +43,9 @@
 
 #include <omapip/omapip_p.h>
 
+OMAPI_OBJECT_ALLOC (omapi_listener,
+                   omapi_listener_object_t, omapi_type_listener)
+
 isc_result_t omapi_listen (omapi_object_t *h,
                           unsigned port,
                           int max)
@@ -68,24 +71,21 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
        struct in_addr ia;
 
        /* Get the handle. */
-       obj = (omapi_listener_object_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       rc_register_mdl (&obj, obj, obj -> refcnt);
-       obj -> type = omapi_type_listener;
+       obj = (omapi_listener_object_t *)0;
+       status = omapi_listener_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        /* Connect this object to the inner object. */
        status = omapi_object_reference (&h -> outer,
                                         (omapi_object_t *)obj, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&obj -> inner, h, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                return status;
        }
 
@@ -108,7 +108,7 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
        /* Create a socket on which to listen. */
        obj -> socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (!obj -> socket) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
                        return ISC_R_NORESOURCES;
                return ISC_R_UNEXPECTED;
@@ -117,7 +117,7 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
 #if defined (HAVE_SETFD)
        if (fcntl (obj -> socket, F_SETFD, 1) < 0) {
                close (obj -> socket);
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
 #endif
@@ -127,7 +127,7 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
        i = bind (obj -> socket,
                  (struct sockaddr *)&obj -> address, sizeof obj -> address);
        if (i < 0) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                if (errno == EADDRINUSE)
                        return ISC_R_ADDRNOTAVAIL;
                if (errno == EPERM)
@@ -137,24 +137,20 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
 
        /* Now tell the kernel to listen for connections. */
        if (listen (obj -> socket, max)) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
 
        if (fcntl (obj -> socket, F_SETFL, O_NONBLOCK) < 0) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_listener_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
 
        status = omapi_register_io_object ((omapi_object_t *)obj,
                                           omapi_listener_readfd, 0,
                                           omapi_accept, 0, 0);
-       if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-               return status;
-       }
-
-       return ISC_R_SUCCESS;
+       omapi_listener_dereference (&obj, MDL);
+       return status;
 }
 
 /* Return the socket on which the dispatcher should wait for readiness
@@ -184,13 +180,10 @@ isc_result_t omapi_accept (omapi_object_t *h)
        listener = (omapi_listener_object_t *)h;
        
        /* Get the handle. */
-       obj = (omapi_connection_object_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       rc_register_mdl (&obj, obj, obj -> refcnt);
-       obj -> type = omapi_type_connection;
+       obj = (omapi_connection_object_t *)0;
+       status = omapi_connection_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        /* Accept the connection. */
        len = sizeof obj -> remote_addr;
@@ -199,7 +192,7 @@ isc_result_t omapi_accept (omapi_object_t *h)
                        ((struct sockaddr *)
                         &(obj -> remote_addr)), &len);
        if (obj -> socket < 0) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS)
                        return ISC_R_NORESOURCES;
                return ISC_R_UNEXPECTED;
@@ -214,18 +207,17 @@ isc_result_t omapi_accept (omapi_object_t *h)
                                           omapi_connection_writer,
                                           omapi_connection_reaper);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_connection_dereference (&obj, MDL);
                return status;
        }
 
-       omapi_object_reference (&obj -> listener,
-                               (omapi_object_t *)listener, MDL);
+       omapi_listener_reference (&obj -> listener, listener, MDL);
 
        status = omapi_signal (h, "connect", obj);
 
        /* Lose our reference to the connection, so it'll be gc'd when it's
           reaped. */
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+       omapi_connection_dereference (&obj, MDL);
        return status;
 }
 
@@ -264,7 +256,7 @@ isc_result_t omapi_listener_destroy (omapi_object_t *h,
 
        if (h -> type != omapi_type_listener)
                return ISC_R_INVALIDARG;
-       l = (omapi_listener_object_t *)(h);
+       l = (omapi_listener_object_t *)h;
        
        if (l -> socket != -1) {
                close (l -> socket);
index d20da511beb21360da4ee8e7c1d0b29544d181e8..60cd68576c37e212cecc7329daceb673acbf4273 100644 (file)
@@ -43,6 +43,9 @@
 
 #include <omapip/omapip_p.h>
 
+OMAPI_OBJECT_ALLOC (omapi_message,
+                   omapi_message_object_t, omapi_type_message)
+
 omapi_message_object_t *omapi_registered_messages;
 
 isc_result_t omapi_message_new (omapi_object_t **o, const char *file, int line)
index f28972830e1daa38972a08bb0fae3b9826a55186..88721babdd1fb66226a51e3de1b406065466f792 100644 (file)
 
 #include <omapip/omapip_p.h>
 
+OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
+                   omapi_type_protocol)
+OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
+                   omapi_type_protocol_listener)
+
 isc_result_t omapi_protocol_connect (omapi_object_t *h,
                                     const char *server_name,
                                     unsigned port,
@@ -51,34 +56,31 @@ isc_result_t omapi_protocol_connect (omapi_object_t *h,
        isc_result_t status;
        omapi_protocol_object_t *obj;
 
-       obj = (omapi_protocol_object_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       rc_register_mdl (&obj, obj, obj -> refcnt);
-       obj -> type = omapi_type_protocol;
+       obj = (omapi_protocol_object_t *)0;
+       status = omapi_protocol_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        status = omapi_connect ((omapi_object_t *)obj, server_name, port);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_protocol_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&h -> outer,
                                         (omapi_object_t *)obj, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_protocol_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&obj -> inner, h, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_protocol_dereference (&obj, MDL);
                return status;
        }
 
        if (authinfo)
                omapi_object_reference (&obj -> authinfo, authinfo, MDL);
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+       omapi_protocol_dereference (&obj, MDL);
        return ISC_R_SUCCESS;
 }
 
@@ -125,16 +127,15 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po,
 {
        omapi_protocol_object_t *p;
        omapi_object_t *c;
-       omapi_message_object_t *m;
-       omapi_message_object_t *om;
+       omapi_message_object_t *m, *om;
        isc_result_t status;
        u_int32_t foo;
 
        if (po -> type != omapi_type_protocol ||
            !po -> outer || po -> outer -> type != omapi_type_connection ||
-           mo -> type != omapi_type_message)
+           m -> type != omapi_type_message)
                return ISC_R_INVALIDARG;
-       if (omo && omo -> type != omapi_type_message)
+       if (om && om -> type != omapi_type_message)
                return ISC_R_INVALIDARG;
        p = (omapi_protocol_object_t *)po;
        c = (omapi_object_t *)(po -> outer);
@@ -305,8 +306,7 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
                /* If we already have the data, fall through. */
 
              case omapi_protocol_header_wait:
-               status = omapi_message_new ((omapi_object_t **)&p -> message,
-                                           MDL);
+               status = omapi_message_allocate (&p -> message, MDL);
                if (status != ISC_R_SUCCESS) {
                        omapi_disconnect (c, 1);
                        return status;
@@ -486,8 +486,7 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
 
                /* XXX unbind the authenticator. */
              auth_unbind:
-               omapi_object_dereference ((omapi_object_t **)&p -> message,
-                                         MDL);
+               omapi_message_dereference (&p -> message, MDL);
 
                /* Now wait for the next message. */
                goto to_header_wait;            
@@ -535,8 +534,7 @@ isc_result_t omapi_protocol_destroy (omapi_object_t *h,
                return ISC_R_INVALIDARG;
        p = (omapi_protocol_object_t *)h;
        if (p -> message)
-               omapi_object_dereference ((omapi_object_t **)&p -> message,
-                                         file, line);
+               omapi_message_dereference (&p -> message, file, line);
        if (p -> authinfo)
                return omapi_object_dereference (&p -> authinfo, file, line);
        return ISC_R_SUCCESS;
@@ -570,27 +568,25 @@ isc_result_t omapi_protocol_listen (omapi_object_t *h,
        isc_result_t status;
        omapi_protocol_listener_object_t *obj;
 
-       obj = (omapi_protocol_listener_object_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       obj -> type = omapi_type_protocol_listener;
+       obj = (omapi_protocol_listener_object_t *)0;
+       status = omapi_protocol_listener_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        status = omapi_object_reference (&h -> outer,
                                         (omapi_object_t *)obj, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_protocol_listener_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&obj -> inner, h, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_protocol_listener_dereference (&obj, MDL);
                return status;
        }
 
        status = omapi_listen ((omapi_object_t *)obj, port, max);
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+       omapi_protocol_listener_dereference (&obj, MDL);
        return status;
 }
 
@@ -621,17 +617,15 @@ isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
        if (!c || c -> type != omapi_type_connection)
                return ISC_R_INVALIDARG;
 
-       obj = (omapi_protocol_object_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       obj -> type = omapi_type_protocol;
+       obj = (omapi_protocol_object_t *)0;
+       status = omapi_protocol_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
 
        status = omapi_object_reference (&obj -> outer, c, MDL);
        if (status != ISC_R_SUCCESS) {
              lose:
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               omapi_protocol_dereference (&obj, MDL);
                omapi_disconnect (c, 1);
                return status;
        }
@@ -648,7 +642,7 @@ isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
        if (status != ISC_R_SUCCESS)
                goto lose;
 
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+       omapi_protocol_dereference (&obj, MDL);
        return status;
 }
 
@@ -712,48 +706,51 @@ isc_result_t omapi_protocol_send_status (omapi_object_t *po,
                                         unsigned rid, const char *msg)
 {
        isc_result_t status;
-       omapi_object_t *message = (omapi_object_t *)0;
+       omapi_message_object_t *message = (omapi_message_object_t *)0;
+       omapi_object_t *mo;
 
        if (po -> type != omapi_type_protocol)
                return ISC_R_INVALIDARG;
 
-       status = omapi_message_new (&message, MDL);
+       status = omapi_message_allocate (&message, MDL);
        if (status != ISC_R_SUCCESS)
                return status;
+       mo = (omapi_object_t *)message;
 
-       status = omapi_set_int_value (message, (omapi_object_t *)0,
+       status = omapi_set_int_value (mo, (omapi_object_t *)0,
                                      "op", OMAPI_OP_STATUS);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference (&message, MDL);
+               omapi_message_dereference (&message, MDL);
                return status;
        }
 
-       status = omapi_set_int_value (message, (omapi_object_t *)0,
+       status = omapi_set_int_value (mo, (omapi_object_t *)0,
                                      "rid", (int)rid);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference (&message, MDL);
+               omapi_message_dereference (&message, MDL);
                return status;
        }
 
-       status = omapi_set_int_value (message, (omapi_object_t *)0,
+       status = omapi_set_int_value (mo, (omapi_object_t *)0,
                                      "result", (int)waitstatus);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference (&message, MDL);
+               omapi_message_dereference (&message, MDL);
                return status;
        }
 
        /* If a message has been provided, send it. */
        if (msg) {
-               status = omapi_set_string_value (message, (omapi_object_t *)0,
+               status = omapi_set_string_value (mo, (omapi_object_t *)0,
                                                 "message", msg);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference (&message, MDL);
+                       omapi_message_dereference (&message, MDL);
                        return status;
                }
        }
 
-       return omapi_protocol_send_message (po,
-                                           id, message, (omapi_object_t *)0);
+       status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
+       omapi_message_dereference (&message, MDL);
+       return status;
 }
 
 isc_result_t omapi_protocol_send_update (omapi_object_t *po,
@@ -762,51 +759,54 @@ isc_result_t omapi_protocol_send_update (omapi_object_t *po,
                                         omapi_object_t *object)
 {
        isc_result_t status;
-       omapi_object_t *message = (omapi_object_t *)0;
+       omapi_message_object_t *message = (omapi_message_object_t *)0;
+       omapi_object_t *mo;
 
        if (po -> type != omapi_type_protocol)
                return ISC_R_INVALIDARG;
 
-       status = omapi_message_new (&message, MDL);
+       status = omapi_message_allocate (&message, MDL);
        if (status != ISC_R_SUCCESS)
                return status;
+       mo = (omapi_object_t *)message;
 
-       status = omapi_set_int_value (message, (omapi_object_t *)0,
+       status = omapi_set_int_value (mo, (omapi_object_t *)0,
                                      "op", OMAPI_OP_UPDATE);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference (&message, MDL);
+               omapi_message_dereference (&message, MDL);
                return status;
        }
 
        if (rid) {
                omapi_handle_t handle;
-               status = omapi_set_int_value (message, (omapi_object_t *)0,
+               status = omapi_set_int_value (mo, (omapi_object_t *)0,
                                              "rid", (int)rid);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference (&message, MDL);
+                       omapi_message_dereference (&message, MDL);
                        return status;
                }
 
                status = omapi_object_handle (&handle, object);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference (&message, MDL);
+                       omapi_message_dereference (&message, MDL);
                        return status;
                }
-               status = omapi_set_int_value (message, (omapi_object_t *)0,
+               status = omapi_set_int_value (mo, (omapi_object_t *)0,
                                              "handle", (int)handle);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference (&message, MDL);
+                       omapi_message_dereference (&message, MDL);
                        return status;
                }
        }               
                
-       status = omapi_set_object_value (message, (omapi_object_t *)0,
+       status = omapi_set_object_value (mo, (omapi_object_t *)0,
                                         "object", object);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference (&message, MDL);
+               omapi_message_dereference (&message, MDL);
                return status;
        }
 
-       return omapi_protocol_send_message (po,
-                                           id, message, (omapi_object_t *)0);
+       status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
+       omapi_message_dereference (&message, MDL);
+       return status;
 }
index 99f449b9c2f51154e01e335b92cb9018526c2edb..a1ceb2c2a9dc9c380de145886b94f4fa0041e471 100644 (file)
@@ -70,7 +70,9 @@ isc_result_t omapi_init (void)
                                             omapi_connection_destroy,
                                             omapi_connection_signal_handler,
                                             omapi_connection_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof
+                                            (omapi_connection_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -81,7 +83,8 @@ isc_result_t omapi_init (void)
                                             omapi_listener_destroy,
                                             omapi_listener_signal_handler,
                                             omapi_listener_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (omapi_listener_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -92,7 +95,8 @@ isc_result_t omapi_init (void)
                                             omapi_io_destroy,
                                             omapi_io_signal_handler,
                                             omapi_io_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (omapi_io_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -103,7 +107,8 @@ isc_result_t omapi_init (void)
                                             omapi_generic_destroy,
                                             omapi_generic_signal_handler,
                                             omapi_generic_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (omapi_generic_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -114,18 +119,19 @@ isc_result_t omapi_init (void)
                                             omapi_protocol_destroy,
                                             omapi_protocol_signal_handler,
                                             omapi_protocol_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (omapi_protocol_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
-       status = omapi_object_type_register (&omapi_type_protocol_listener,
-                                            "protocol-listener",
-                                            omapi_protocol_listener_set_value,
-                                            omapi_protocol_listener_get_value,
-                                            omapi_protocol_listener_destroy,
-                                            omapi_protocol_listener_signal,
-                                            omapi_protocol_listener_stuff,
-                                            0, 0, 0);
+       status = (omapi_object_type_register
+                 (&omapi_type_protocol_listener, "protocol-listener",
+                  omapi_protocol_listener_set_value,
+                  omapi_protocol_listener_get_value,
+                  omapi_protocol_listener_destroy,
+                  omapi_protocol_listener_signal,
+                  omapi_protocol_listener_stuff,
+                  0, 0, 0, 0, 0, sizeof (omapi_protocol_listener_object_t)));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -136,7 +142,8 @@ isc_result_t omapi_init (void)
                                             omapi_message_destroy,
                                             omapi_message_signal_handler,
                                             omapi_message_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (omapi_message_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -146,7 +153,8 @@ isc_result_t omapi_init (void)
                                             0,
                                             0,
                                             omapi_waiter_signal_handler, 0,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (omapi_waiter_object_t));
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -185,7 +193,12 @@ isc_result_t omapi_object_type_register (omapi_object_type_t **type,
                                                 omapi_object_t *),
                                         isc_result_t (*remove)
                                                (omapi_object_t *,
-                                                omapi_object_t *))
+                                                omapi_object_t *),
+                                        isc_result_t (*freer)
+                                               (omapi_object_t *,
+                                                const char *, int),
+                                        isc_result_t (*sizer) (size_t),
+                                        size_t size)
 {
        omapi_object_type_t *t;
 
@@ -204,6 +217,9 @@ isc_result_t omapi_object_type_register (omapi_object_type_t **type,
        t -> create = create;
        t -> remove = remove;
        t -> next = omapi_object_types;
+       t -> sizer = sizer;
+       t -> size = size;
+       t -> freer = freer;
        omapi_object_types = t;
        if (type)
                *type = t;
index 956ae0777d7ed64475aa81de3d51c463859d49ed..77ea85f58b2ca18fabf4c111adfa0bf50275b4e4 100644 (file)
@@ -15,7 +15,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
+ * 3. Neither the name of Internet Software Consortium nor the names
  *    of its contributors may be used to endorse or promote products derived
  *    from this software without specific prior written permission.
  *
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhcrelay.c,v 1.40 2000/03/17 04:00:27 mellon Exp $ Copyright (c) 1997-2000The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhcrelay.c,v 1.41 2000/05/16 23:03:30 mellon Exp $ Copyright (c) 1997-2000 Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -108,7 +108,7 @@ struct server_list {
 } *servers;
 
 static char copyright [] =
-"Copyright 1997, 1998, 1999 The Internet Software Consortium.";
+"Copyright 1997, 1998, 1999 Internet Software Consortium.";
 static char arr [] = "All rights reserved.";
 static char message [] = "Internet Software Consortium DHCP Relay Agent";
 static char contrib [] = "\nPlease contribute if you find this software useful.";
@@ -325,11 +325,6 @@ void relay (ip, packet, length, from_port, from, hfrom)
                return;
        }
 
-       /* XXX Dave:
-          If you're using the circuit ID to figure out where to
-          send the reply, you can delete the following code,
-          but you still need to validate the giaddr and drop the
-          packet if it's bogus. */
        /* Find the interface that corresponds to the giaddr
           in the packet. */
        if (packet -> giaddr.s_addr) {
@@ -467,10 +462,10 @@ void dhcp (packet)
 {
 }
 
-struct subnet *find_subnet (addr)
-       struct iaddr addr;
+int find_subnet (struct subnet **sp,
+                struct iaddr addr, const char *file, int line)
 {
-       return (struct subnet *)0;
+       return 0;
 }
 
 /* Strip any Relay Agent Information options from the DHCP packet
index 1a7b372f01343f67722ccf2f11b3a38c5d44d5b4..01a6f429b7a6f5e3e88fad911c53e8618922e2a9 100644 (file)
@@ -20,9 +20,9 @@
 CATMANPAGES = dhcpd.cat8 dhcpd.conf.cat5 dhcpd.leases.cat5
 SEDMANPAGES = dhcpd.man8 dhcpd.conf.man5 dhcpd.leases.man5
 SRCS   = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
-        omapi.c mdb.c stables.c
+        omapi.c mdb.c stables.c salloc.c
 OBJS   = dhcpd.o dhcp.o bootp.o confpars.o db.o class.o failover.o \
-        omapi.o mdb.o stables.o
+        omapi.o mdb.o stables.o salloc.o
 PROG   = dhcpd
 MAN    = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
 
index 6062a4366c28cdb01d15c72817074b11ec7b1aee..0d85558f9423222d0d4fbb80b464082998da586e 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: bootp.c,v 1.62 2000/05/03 22:57:42 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: bootp.c,v 1.63 2000/05/16 23:03:35 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -52,7 +52,7 @@ void bootp (packet)
        struct packet *packet;
 {
        int result;
-       struct host_decl *hp;
+       struct host_decl *hp = (struct host_decl *)0;
        struct host_decl *host = (struct host_decl *)0;
        struct packet outgoing;
        struct dhcp_packet raw;
@@ -88,52 +88,66 @@ void bootp (packet)
                return;
        }
 
-       hp = find_hosts_by_haddr (packet -> raw -> htype,
-                                 packet -> raw -> chaddr,
-                                 packet -> raw -> hlen);
+       find_hosts_by_haddr (&hp, packet -> raw -> htype,
+                            packet -> raw -> chaddr,
+                            packet -> raw -> hlen, MDL);
 
-       lease = find_lease (packet, packet -> shared_network, 0);
+       lease  = (struct lease *)0;
+       find_lease (&lease, packet, packet -> shared_network, 0, MDL);
 
        /* Find an IP address in the host_decl that matches the
           specified network. */
+       subnet = (struct subnet *)0;
        if (hp)
-               subnet = find_host_for_network (&hp, &ip_address,
-                                               packet -> shared_network);
-       else
-               subnet = (struct subnet *)0;
+               find_host_for_network (&subnet, &hp, &ip_address,
+                                      packet -> shared_network);
 
        if (!subnet) {
+               struct host_decl *h;
                /* We didn't find an applicable host declaration.
                   Just in case we may be able to dynamically assign
                   an address, see if there's a host declaration
                   that doesn't have an ip address associated with it. */
-               if (hp) {
-                       for (; hp; hp = hp -> n_ipaddr) {
-                               if (!hp -> fixed_addr) {
-                                       host = hp;
-                                       break;
-                               }
+               for (h = hp; h; h = h -> n_ipaddr) {
+                       if (!h -> fixed_addr) {
+                               host_reference (&host, h, MDL);
+                               break;
                        }
                }
+               if (hp) {
+                       host_dereference (&hp, MDL);
+                       if (host)
+                               host_reference (&hp, host, MDL);
+               }                       
 
                /* If a lease has already been assigned to this client,
                   use it. */
                if (lease) {
+                       if (host && host != lease -> host) {
+                               if (lease -> host)
+                                       host_dereference (&lease -> host, MDL);
+                               host_reference (&lease -> host, host, MDL);
+                       }
                        ack_lease (packet, lease, 0, 0, msgbuf, 0);
-                       return;
+                       goto out;
                }
 
                /* Otherwise, try to allocate one. */
-               lease = allocate_lease (packet,
-                                       packet -> shared_network -> pools, 0,
-                                       &peer_has_leases);
+               allocate_lease (&lease, packet,
+                               packet -> shared_network -> pools,
+                               &peer_has_leases);
                if (lease) {
-                       lease -> host = host;
+                       if (host && host != lease -> host) {
+                               if (lease -> host)
+                                       host_dereference (&lease -> host, MDL);
+                               host_reference (&lease -> host, host, MDL);
+                       } else if (lease -> host)
+                               host_dereference (&lease -> host, MDL);
                        ack_lease (packet, lease, 0, 0, msgbuf, 0);
-                       return;
+                       goto out;
                }
                log_info ("%s: no available leases", msgbuf);
-               return;
+               goto out;
        }
 
        /* Run the executable statements to compute the client and server
@@ -165,9 +179,7 @@ void bootp (packet)
                                            &lease -> scope, oc, MDL)) {
                if (!ignorep)
                        log_info ("%s: bootp disallowed", msgbuf);
-               option_state_dereference (&options, MDL);
-               static_lease_dereference (lease, MDL);
-               return;
+               goto out;
        } 
 
        if ((oc = lookup_option (&server_universe,
@@ -177,9 +189,7 @@ void bootp (packet)
                                            &lease -> scope, oc, MDL)) {
                if (!ignorep)
                        log_info ("%s: booting disallowed", msgbuf);
-               option_state_dereference (&options, MDL);
-               static_lease_dereference (lease, MDL);
-               return;
+               goto out;
        }
 
        /* Set up the outgoing packet... */
@@ -347,7 +357,7 @@ void bootp (packet)
                                              (struct packet *)0,
                                              &raw, outgoing.packet_length,
                                              from, &to, &hto);
-                       return;
+                       goto out;
                }
 
        /* If it comes from a client that already knows its address
@@ -369,4 +379,17 @@ void bootp (packet)
        result = send_packet (packet -> interface,
                              packet, &raw, outgoing.packet_length,
                              from, &to, &hto);
+      out:
+       if (options)
+               option_state_dereference (&options, MDL);
+       if (lease) {
+               static_lease_dereference (lease, MDL);
+               lease_dereference (&lease, MDL);
+       }
+       if (hp)
+               host_dereference (&hp, MDL);
+       if (host)
+               host_dereference (&host, MDL);
+       if (subnet)
+               subnet_dereference (&subnet, MDL);
 }
index 717470422c2ee02e08a0f21e132c5c6cb7a4012c..d02ce08dbbc3642dbcbcf4c289fdf10af5c7838f 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: class.c,v 1.19 2000/03/18 02:15:52 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: class.c,v 1.20 2000/05/16 23:03:36 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium.  All rights reserved.\n";
 
 #endif /* not lint */
 
@@ -113,10 +113,10 @@ int check_collection (packet, lease, collection)
                                   packet -> options, (struct option_state *)0,
                                   &lease -> scope, class -> submatch));
                        if (status) {
-                               if ((nc = ((struct class *)
-                                          hash_lookup (class -> hash,
-                                                       data.data,
-                                                       data.len)))) {
+                               nc = (struct class *)0;
+                               if (class_hash_lookup (&nc, class -> hash,
+                                                      (const char *)data.data,
+                                                      data.len, MDL)) {
 #if defined (DEBUG_CLASS_MATCHING)
                                        log_info ("matches subclass %s.",
                                              print_hex_1 (data.len,
@@ -168,10 +168,11 @@ int check_collection (packet, lease, collection)
                                data_string_forget (&data, MDL);
                                if (!class -> hash)
                                        class -> hash = new_hash (0, 0, 0);
-                               add_hash (class -> hash,
-                                         nc -> hash_string.data,
-                                         nc -> hash_string.len,
-                                         (unsigned char *)nc);
+                               class_hash_add (class -> hash,
+                                               (const char *)
+                                               nc -> hash_string.data,
+                                               nc -> hash_string.len,
+                                               nc, MDL);
                                classify (packet, nc);
                        }
                }
@@ -196,7 +197,8 @@ void classify (packet, class)
        struct class *class;
 {
        if (packet -> class_count < PACKET_MAX_CLASSES)
-               packet -> classes [packet -> class_count++] = class;
+               class_reference (&packet -> classes [packet -> class_count++],
+                                class, MDL);
        else
                log_error ("too many groups for %s",
                      print_hw_addr (packet -> raw -> htype,
@@ -204,18 +206,19 @@ void classify (packet, class)
                                     packet -> raw -> chaddr));
 }
 
-struct class *find_class (name)
-       const char *name;
+isc_result_t find_class (struct class **class, const char *name,
+                        const char *file, int line)
 {
        struct collection *lp;
        struct class *cp;
 
        for (lp = collections; lp; lp = lp -> next) {
                for (cp = lp -> classes; cp; cp = cp -> nic)
-                       if (cp -> name && !strcmp (name, cp -> name))
-                               return cp;
+                       if (cp -> name && !strcmp (name, cp -> name)) {
+                               return class_reference (class, cp, file, line);
+                       }
        }
-       return (struct class *)0;
+       return ISC_R_NOTFOUND;
 }
 
 int unbill_class (lease, class)
@@ -232,8 +235,8 @@ int unbill_class (lease, class)
                      piaddr (lease -> ip_addr));
                return 0;
        }
-       lease -> billing_class = (struct class *)0;
-       class -> billed_leases [i] = (struct lease *)0;
+       class_dereference (&lease -> billing_class, MDL);
+       lease_dereference (&class -> billed_leases [i], MDL);
        class -> leases_consumed--;
        return 1;
 }
@@ -256,8 +259,8 @@ int bill_class (lease, class)
                return 0;
        }
 
-       class -> billed_leases [i] = lease;
-       lease -> billing_class = class;
+       lease_reference (&class -> billed_leases [i], lease, MDL);
+       class_reference (&lease -> billing_class, class, MDL);
        class -> leases_consumed++;
        return 1;
 }
index 50f0c5b50e56cee7d8efeabccc5b4a9849198913..cd3a318a7017324a7cfb3c412dee8e281836e232 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.109 2000/05/04 18:58:11 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.110 2000/05/16 23:03:37 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -55,6 +55,16 @@ static TIME parsed_time;
    declarations :== <nil> | declaration | declarations declaration */
 
 isc_result_t readconf ()
+{
+       return parse_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP);
+}
+
+/* conf-file :== parameters declarations EOF
+   parameters :== <nil> | parameter | parameters parameter
+   declarations :== <nil> | declaration | declarations declaration */
+
+isc_result_t parse_conf_file (const char *filename, struct group *group,
+                             int group_type)
 {
        int file;
        struct parse *cfile;
@@ -63,18 +73,17 @@ isc_result_t readconf ()
        int declaration = 0;
        int status;
 
-       if ((file = open (path_dhcpd_conf, O_RDONLY)) < 0)
-               log_fatal ("Can't open %s: %m", path_dhcpd_conf);
+       if ((file = open (filename, O_RDONLY)) < 0)
+               log_fatal ("Can't open %s: %m", filename);
 
        cfile = (struct parse *)0;
-       new_parse (&cfile, file, (char *)0, 0, path_dhcpd_conf);
+       new_parse (&cfile, file, (char *)0, 0, filename);
 
        do {
                token = peek_token (&val, cfile);
                if (token == EOF)
                        break;
-               declaration = parse_statement (cfile, &root_group,
-                                              ROOT_GROUP,
+               declaration = parse_statement (cfile, group, group_type,
                                               (struct host_decl *)0,
                                               declaration);
        } while (1);
@@ -125,9 +134,8 @@ isc_result_t read_leases ()
                if (token == EOF)
                        break;
                if (token == LEASE) {
-                       struct lease *lease;
-                       lease = parse_lease_declaration (cfile);
-                       if (lease) {
+                       struct lease *lease = (struct lease *)0;
+                       if (parse_lease_declaration (&lease, cfile)) {
                                enter_lease (lease);
                                if (lease -> on_expiry)
                                        executable_statement_dereference
@@ -138,13 +146,14 @@ isc_result_t read_leases ()
                                if (lease -> on_release)
                                        executable_statement_dereference
                                                (&lease -> on_release, MDL);
+                               lease_dereference (&lease, MDL);
                        } else
                                parse_warn (cfile,
                                            "possibly corrupt lease file");
                } else if (token == HOST) {
-                       parse_host_declaration (cfile, &root_group);
+                       parse_host_declaration (cfile, root_group);
                } else if (token == GROUP) {
-                       parse_group_declaration (cfile, &root_group);
+                       parse_group_declaration (cfile, root_group);
 #if defined (FAILOVER_PROTOCOL)
                } else if (token == FAILOVER) {
                        parse_failover_state_declaration
@@ -217,10 +226,25 @@ int parse_statement (cfile, group, type, host_decl, declaration)
        int lose;
        struct data_string key_id;
        int known;
+       isc_result_t status;
 
        token = peek_token (&val, cfile);
 
        switch (token) {
+             case INCLUDE:
+               next_token (&val, cfile);
+               token = next_token (&val, cfile);
+               if (token != STRING) {
+                       parse_warn (cfile, "filename string expected.");
+                       skip_to_semi (cfile);
+               } else {
+                       status = parse_conf_file (val, group, type);
+                       if (status != ISC_R_SUCCESS)
+                               parse_warn (cfile, "%s: bad parse.", val);
+                       parse_semi (cfile);
+               }
+               return 1;
+               
              case HOST:
                next_token (&val, cfile);
                if (type != HOST_DECL && type != CLASS_DECL)
@@ -283,18 +307,23 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                /* Otherwise, cons up a fake shared network structure
                   and populate it with the lone subnet... */
 
-               share = new_shared_network (MDL);
-               if (!share)
-                       log_fatal ("No memory for shared subnet");
-               share -> group = clone_group (group, MDL);
-               share -> group -> shared_network = share;
+               share = (struct shared_network *)0;
+               status = shared_network_allocate (&share, MDL);
+               if (status != ISC_R_SUCCESS)
+                       log_fatal ("Can't allocate shared subnet: %s",
+                                  isc_result_totext (status));
+               if (!clone_group (&share -> group, group, MDL))
+                       log_fatal ("Can't allocate group for shared subnet.");
+               shared_network_reference (&share -> group -> shared_network,
+                                         share, MDL);
 
                parse_subnet_declaration (cfile, share);
 
                /* share -> subnets is the subnet we just parsed. */
                if (share -> subnets) {
-                       share -> interface =
-                               share -> subnets -> interface;
+                       interface_reference (&share -> interface,
+                                            share -> subnets -> interface,
+                                            MDL);
 
                        /* Make the shared network name from network number. */
                        n = piaddr (share -> subnets -> net);
@@ -320,7 +349,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                        skip_to_semi (cfile);
                        break;
                }
-               parse_class_declaration (cfile, group, 0);
+               parse_class_declaration ((struct class **)0, cfile, group, 0);
                return 1;
 
              case USER_CLASS:
@@ -331,7 +360,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                        skip_to_semi (cfile);
                        break;
                }
-               parse_class_declaration (cfile, group, 1);
+               parse_class_declaration ((struct class **)0, cfile, group, 1);
                return 1;
 
              case CLASS:
@@ -342,7 +371,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                        skip_to_semi (cfile);
                        break;
                }
-               parse_class_declaration (cfile, group, 2);
+               parse_class_declaration ((struct class **)0, cfile, group, 2);
                return 1;
 
              case SUBCLASS:
@@ -353,7 +382,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                        skip_to_semi (cfile);
                        break;
                }
-               parse_class_declaration (cfile, group, 3);
+               parse_class_declaration ((struct class **)0, cfile, group, 3);
                return 1;
 
              case HARDWARE:
@@ -369,13 +398,15 @@ int parse_statement (cfile, group, type, host_decl, declaration)
              case FIXED_ADDR:
                next_token (&val, cfile);
                cache = (struct option_cache *)0;
-               parse_fixed_addr_param (&cache, cfile);
-               if (host_decl)
-                       host_decl -> fixed_addr = cache;
-               else {
-                       parse_warn (cfile, "fixed-address parameter not %s",
-                                   "allowed here.");
-                       option_cache_dereference (&cache, MDL);
+               if (parse_fixed_addr_param (&cache, cfile)) {
+                       if (host_decl)
+                               host_decl -> fixed_addr = cache;
+                       else {
+                               parse_warn (cfile,
+                                           "fixed-address parameter not %s",
+                                           "allowed here.");
+                               option_cache_dereference (&cache, MDL);
+                       }
                }
                break;
 
@@ -612,7 +643,7 @@ void parse_failover_peer (cfile, group, type)
 
        /* See if there's a peer declaration by this name. */
        peer = (dhcp_failover_state_t *)0;
-       find_failover_peer (&peer, name);
+       find_failover_peer (&peer, name, MDL);
 
        token = next_token (&val, cfile);
        if (token == SEMI) {
@@ -626,9 +657,11 @@ void parse_failover_peer (cfile, group, type)
                                            " failover peer ", name);
                                return;
                        }
-                       group -> shared_network -> failover_peer =
-                               peer;
+                       dhcp_failover_state_reference
+                               (&group -> shared_network -> failover_peer,
+                                peer, MDL);
                }
+               dhcp_failover_state_dereference (&peer, MDL);
                return;
        } else if (token == STATE) {
                if (!peer) {
@@ -637,6 +670,7 @@ void parse_failover_peer (cfile, group, type)
                        return;
                }
                parse_failover_state_declaration (cfile, peer);
+               dhcp_failover_state_dereference (&peer, MDL);
                return;
        } else if (token != LBRACE) {
                parse_warn (cfile, "expecting left brace");
@@ -647,15 +681,14 @@ void parse_failover_peer (cfile, group, type)
        if (peer) {
                parse_warn (cfile, "redeclaration of failover peer %s", name);
                skip_to_rbrace (cfile, 1);
+               dhcp_failover_state_dereference (&peer, MDL);
                return;
        }
 
-       peer = dmalloc (sizeof *peer, MDL);
-       if (!peer)
-               log_fatal ("no memory for failover peer%s.", name);
-       memset (peer, 0, sizeof *peer);
-       peer -> refcnt = 1;
-       peer -> type = dhcp_type_failover_state;
+       status = dhcp_failover_state_allocate (&peer, MDL);
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Can't allocate failover peer %s: %s",
+                          name, isc_result_totext (status));
 
        /* Save the name. */
        peer -> name = name;
@@ -693,6 +726,7 @@ void parse_failover_peer (cfile, group, type)
                                parse_warn (cfile,
                                            "expecting 'address' or 'port'");
                                skip_to_rbrace (cfile, 1);
+                               dhcp_failover_state_dereference (&peer, MDL);
                                return;
                        }
                        break;
@@ -703,6 +737,7 @@ void parse_failover_peer (cfile, group, type)
                        expr = (struct expression *)0;
                        if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
                                skip_to_rbrace (cfile, 1);
+                               dhcp_failover_state_dereference (&peer, MDL);
                                return;
                        }
                        option_cache (paddr, (struct data_string *)0, expr,
@@ -732,6 +767,7 @@ void parse_failover_peer (cfile, group, type)
                        if (token != NUMBER) {
                                parse_warn (cfile, "expecting number.");
                                skip_to_rbrace (cfile, 1);
+                               dhcp_failover_state_dereference (&peer, MDL);
                                return;
                        }
                        *tp = atoi (val);
@@ -750,6 +786,7 @@ void parse_failover_peer (cfile, group, type)
                        if (!parse_numeric_aggregate (cfile, hba, &hba_len,
                                                      COLON, 16, 8)) {
                                skip_to_rbrace (cfile, 1);
+                               dhcp_failover_state_dereference (&peer, MDL);
                                return;
                        }
                        if (hba_len != 32) {
@@ -771,13 +808,14 @@ void parse_failover_peer (cfile, group, type)
                        token = next_token (&val, cfile);
                        if (token != NUMBER) {
                                parse_warn (cfile, "expecting number");
+                             badsplit:
                                skip_to_rbrace (cfile, 1);
-                       }
-                       split = atoi (val);
-                       if (!parse_semi (cfile)) {
-                               skip_to_rbrace (cfile, 1);
+                               dhcp_failover_state_dereference (&peer, MDL);
                                return;
                        }
+                       split = atoi (val);
+                       if (!parse_semi (cfile))
+                               goto badsplit;
                        if (split > 255) {
                                parse_warn (cfile, "split must be < 256");
                        } else {
@@ -820,10 +858,12 @@ void parse_failover_peer (cfile, group, type)
                        parse_warn (cfile,
                                    "invalid statement in peer declaration");
                        skip_to_rbrace (cfile, 1);
+                       dhcp_failover_state_dereference (&peer, MDL);
                        return;
                }
                if (token != RBRACE && !parse_semi (cfile)) {
                        skip_to_rbrace (cfile, 1);
+                       dhcp_failover_state_dereference (&peer, MDL);
                        return;
                }
        } while (token != RBRACE);
@@ -835,6 +875,7 @@ void parse_failover_peer (cfile, group, type)
        if (status != ISC_R_SUCCESS)
                parse_warn (cfile, "failover peer %s: %s",
                            peer -> name, isc_result_totext (status));
+       dhcp_failover_state_dereference (&peer, MDL);
 }
 
 void parse_failover_state_declaration (struct parse *cfile,
@@ -868,7 +909,7 @@ void parse_failover_state_declaration (struct parse *cfile,
 
                /* See if there's a peer declaration by this name. */
                state = (dhcp_failover_state_t *)0;
-               find_failover_peer (&state, name);
+               find_failover_peer (&state, name, MDL);
                if (!state) {
                        parse_warn (cfile, "unknown failover peer: %s", name);
                        skip_to_semi (cfile);
@@ -882,13 +923,16 @@ void parse_failover_state_declaration (struct parse *cfile,
                                skip_to_semi (cfile);
                        return;
                }
-       } else
-               state = peer;
+       } else {
+               state = (dhcp_failover_state_t *)0;
+               dhcp_failover_state_reference (&state, peer, MDL);
+       }
        token = next_token (&val, cfile);
        if (token != LBRACE) {
                parse_warn (cfile, "expecting left brace");
                if (token != SEMI)
                        skip_to_semi (cfile);
+               dhcp_failover_state_dereference (&state, MDL);
                return;
        }
        do {
@@ -900,8 +944,7 @@ void parse_failover_state_declaration (struct parse *cfile,
                        token = next_token (&val, cfile);
                        if (token != STATE) {
                                parse_warn (cfile, "expecting 'state'");
-                               skip_to_rbrace (cfile, 1);
-                               return;
+                               goto bogus;
                        }
                        parse_failover_state (cfile,
                                              &state -> my_state,
@@ -911,19 +954,21 @@ void parse_failover_state_declaration (struct parse *cfile,
                        token = next_token (&val, cfile);
                        if (token != STATE) {
                                parse_warn (cfile, "expecting 'state'");
-                               skip_to_rbrace (cfile, 1);
-                               return;
+                               goto bogus;
                        }
                        parse_failover_state (cfile,
                                              &state -> partner_state,
                                              &state -> partner_stos);
                        break;
                      default:
+                     bogus:
                        parse_warn (cfile, "expecting state setting.");
-                       skip_to_rbrace (cfile, 1);
+                       skip_to_rbrace (cfile, 1);      
+                       dhcp_failover_state_dereference (&state, MDL);
                        return;
                }
        } while (token != RBRACE);
+       dhcp_failover_state_dereference (&state, MDL);
 }
 
 void parse_failover_state (cfile, state, stos)
@@ -1005,29 +1050,34 @@ void parse_pool_statement (cfile, group, type)
        int declaration = 0;
        isc_result_t status;
 
-       pool = new_pool (MDL);
-       if (!pool)
+       pool = (struct pool *)0;
+       status = pool_allocate (&pool, MDL);
+       if (status != ISC_R_SUCCESS)
                log_fatal ("no memory for pool.");
 
-       pool -> group = clone_group (group, MDL);
+       clone_group (&pool -> group, group, MDL);
 
        if (type == SUBNET_DECL)
-               pool -> shared_network = group -> subnet -> shared_network;
+               shared_network_reference (&pool -> shared_network,
+                                         group -> subnet -> shared_network,
+                                         MDL);
        else
-               pool -> shared_network = group -> shared_network;
+               shared_network_reference (&pool -> shared_network,
+                                         group -> shared_network, MDL);
 
 #if defined (FAILOVER_PROTOCOL)
        /* Inherit the failover peer from the shared network. */
        if (pool -> shared_network -> failover_peer)
-           omapi_object_reference ((omapi_object_t **)
-                                   &pool -> failover_peer, 
-                                   (omapi_object_t *)
-                                   pool -> shared_network -> failover_peer,
-                                   MDL);
+           dhcp_failover_state_reference
+                   (&pool -> failover_peer, 
+                    pool -> shared_network -> failover_peer, MDL);
 #endif
 
-       if (!parse_lbrace (cfile))
+       if (!parse_lbrace (cfile)) {
+               pool_dereference (&pool, MDL);
                return;
+       }
+
        do {
                token = peek_token (&val, cfile);
                switch (token) {
@@ -1043,10 +1093,8 @@ void parse_pool_statement (cfile, group, type)
                        }
 #if defined (FAILOVER_PROTOCOL)
                        if (pool -> failover_peer)
-                               omapi_object_dereference
-                                       ((omapi_object_t **)
-                                        &pool -> failover_peer, MDL);
-                       /* XXX Flag error if there's no failover peer? */
+                               dhcp_failover_state_dereference
+                                       (&pool -> failover_peer, MDL);
 #endif
                        break;
                                
@@ -1066,11 +1114,10 @@ void parse_pool_statement (cfile, group, type)
                                break;
                        }
                        if (pool -> failover_peer)
-                               omapi_object_dereference
-                                       ((omapi_object_t **)
-                                        &pool -> failover_peer, MDL);
+                               dhcp_failover_state_dereference
+                                       (&pool -> failover_peer, MDL);
                        status = find_failover_peer (&pool -> failover_peer,
-                                                    val);
+                                                    val, MDL);
                        if (status != ISC_R_SUCCESS)
                                parse_warn (cfile,
                                            "failover peer %s: %s", val,
@@ -1152,7 +1199,8 @@ void parse_pool_statement (cfile, group, type)
                                        continue;
                                }
                                permit -> type = permit_class;
-                               permit -> class = find_class (val);
+                               permit -> class = (struct class *)0;
+                               find_class (&permit -> class, val, MDL);
                                if (!permit -> class)
                                        parse_warn (cfile,
                                                    "no such class: %s", val);
@@ -1227,15 +1275,11 @@ void parse_pool_statement (cfile, group, type)
       clash_testing_done:                              
 #endif /* FAILOVER_PROTOCOL */
 
-       if (type == SUBNET_DECL)
-               pool -> shared_network = group -> subnet -> shared_network;
-       else
-               pool -> shared_network = group -> shared_network;
-
        p = &pool -> shared_network -> pools;
        for (; *p; p = &((*p) -> next))
                ;
-       *p = pool;
+       pool_reference (p, pool, MDL);
+       pool_dereference (&pool, MDL);
 }
 
 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
@@ -1298,24 +1342,26 @@ void parse_host_declaration (cfile, group)
        int deleted = 0;
        isc_result_t status;
 
-       token = peek_token (&val, cfile);
-       if (token != LBRACE) {
-               name = parse_host_name (cfile);
-               if (!name)
-                       return;
-       } else {
-               name = (char *)0;
-       }
+       name = parse_host_name (cfile);
+       if (!name)
+               return;
 
-       host = (struct host_decl *)dmalloc (sizeof (struct host_decl), MDL);
-       if (!host)
-               log_fatal ("can't allocate host decl struct %s.", name);
-       memset (host, 0, sizeof *host);
+       host = (struct host_decl *)0;
+       status = host_allocate (&host, MDL);
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("can't allocate host decl struct %s: %s",
+                          name, isc_result_totext (status));
        host -> name = name;
-       host -> group = clone_group (group, MDL);
+       if (clone_group (&host -> group, group, MDL) != ISC_R_SUCCESS) {
+               log_fatal ("can't clone group for host %s: %s",
+                          name, isc_result_totext (status));
+             boom:
+               host_dereference (&host, MDL);
+               return;
+       }
 
        if (!parse_lbrace (cfile))
-               return;
+               goto boom;
 
        do {
                token = peek_token (&val, cfile);
@@ -1357,22 +1403,18 @@ void parse_host_declaration (cfile, group)
                                skip_to_rbrace (cfile, 1);
                                break;
                        }
-                       go = ((struct group_object *)
-                             hash_lookup (group_name_hash,
-                                          (const unsigned char *)val,
-                                          strlen (val)));
-                       if (!go) {
+                       go = (struct group_object *)0;
+                       if (!group_hash_lookup (&go, group_name_hash,
+                                               val, strlen (val), MDL)) {
                            parse_warn (cfile, "unknown group %s in host %s",
                                        val, host -> name);
                        } else {
                                if (host -> named_group)
-                                       omapi_object_dereference
-                                               ((omapi_object_t **)
-                                                &host -> named_group, MDL);
-                               omapi_object_reference
-                                       ((omapi_object_t **)
-                                        &host -> named_group,
-                                        (omapi_object_t *)go, MDL);
+                                       group_object_dereference
+                                               (&host -> named_group, MDL);
+                               group_object_reference (&host -> named_group,
+                                                       go, MDL);
+                               group_object_dereference (&go, MDL);
                        }
                        if (!parse_semi (cfile))
                                break;
@@ -1429,28 +1471,26 @@ void parse_host_declaration (cfile, group)
        } while (1);
 
        if (deleted) {
-               struct host_decl *hp =
-                       (struct host_decl *)
-                       hash_lookup (host_name_hash,
-                                    (unsigned char *)host -> name,
-                                    strlen (host -> name));
-               if (hp) {
+               struct host_decl *hp = (struct host_decl *)0;
+               if (host_hash_lookup (&hp, host_name_hash,
+                                     (unsigned char *)host -> name,
+                                     strlen (host -> name), MDL)) {
                        delete_host (hp, 0);
+                       host_dereference (&hp, MDL);
                }
-               dfree (host -> name, MDL);
-               if (host -> group)
-                       free_group (host -> group, MDL);
-               dfree (host, MDL);
        } else {
                if (host -> named_group && host -> named_group -> group) {
                        if (host -> group -> statements ||
                            (host -> group -> authoritative !=
                             host -> named_group -> group -> authoritative))
-                               host -> group -> next =
-                                       host -> named_group -> group;
+                               group_reference (&host -> group -> next,
+                                                host -> named_group -> group,
+                                                MDL);
                        else {
-                               dfree (host -> group, MDL);
-                               host -> group = host -> named_group -> group;
+                               group_dereference (&host -> group, MDL);
+                               group_reference (&host -> group,
+                                                host -> named_group -> group,
+                                                MDL);
                        }
                }
                                
@@ -1464,19 +1504,21 @@ void parse_host_declaration (cfile, group)
                        parse_warn (cfile, "host %s: %s", host -> name,
                                    isc_result_totext (status));
        }
+       host_dereference (&host, MDL);
 }
 
 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
 */
 
-struct class *parse_class_declaration (cfile, group, type)
+int parse_class_declaration (cp, cfile, group, type)
+       struct class **cp;
        struct parse *cfile;
        struct group *group;
        int type;
 {
        const char *val;
        enum dhcp_token token;
-       struct class *class = (struct class *)0, *pc;
+       struct class *class = (struct class *)0, *pc = (struct class *)0;
        int declaration = 0;
        int lose = 0;
        struct data_string data;
@@ -1484,22 +1526,23 @@ struct class *parse_class_declaration (cfile, group, type)
        struct executable_statement *stmt = (struct executable_statement *)0;
        struct expression *expr;
        int new = 1;
+       isc_result_t status;
 
        token = next_token (&val, cfile);
        if (token != STRING) {
                parse_warn (cfile, "Expecting class name");
                skip_to_semi (cfile);
-               return (struct class *)0;
+               return 0;
        }
 
        /* See if there's already a class with the specified name. */
-       pc = (struct class *)find_class (val);
+       find_class (&pc, val, MDL);
 
        /* If this isn't a subclass, we're updating an existing class. */
        if (pc && type != 0 && type != 1 && type != 3) {
-               class = pc;
+               class_reference (&class, pc, MDL);
                new = 0;
-               pc = (struct class *)0;
+               class_dereference (&pc, MDL);
        }
 
        /* If this _is_ a subclass, there _must_ be a class with the
@@ -1507,7 +1550,7 @@ struct class *parse_class_declaration (cfile, group, type)
        if (!pc && (type == 0 || type == 1 || type == 3)) {
                parse_warn (cfile, "no class named %s", val);
                skip_to_semi (cfile);
-               return (struct class *)0;
+               return 0;
        }
 
        /* The old vendor-class and user-class declarations had an implicit
@@ -1521,19 +1564,23 @@ struct class *parse_class_declaration (cfile, group, type)
                data.len = strlen (val);
                data.buffer = (struct buffer *)0;
                if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
-                       log_fatal ("no memoy for class name.");
+                       log_fatal ("no memory for class name.");
                data.data = &data.buffer -> data [0];
                data.terminated = 1;
 
                name = type ? "implicit-vendor-class" : "implicit-user-class";
        } else if (type == 2) {
+               name = val;
+       } else {
+               name = (char *)0;
+       }
+
+       if (name) {
                char *tname;
                if (!(tname = dmalloc (strlen (val) + 1, MDL)))
                        log_fatal ("No memory for class name %s.", val);
                strcpy (tname, val);
                name = tname;
-       } else {
-               name = (char *)0;
        }
 
        /* If this is a straight subclass, parse the hash string. */
@@ -1543,37 +1590,42 @@ struct class *parse_class_declaration (cfile, group, type)
                        token = next_token (&val, cfile);
                        data.len = strlen (val);
                        data.buffer = (struct buffer *)0;
-                       if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
-                               return (struct class *)0;
+                       if (!buffer_allocate (&data.buffer,
+                                             data.len + 1, MDL)) {
+                               if (pc)
+                                       class_dereference (&pc, MDL);
+                               
+                               return 0;
+                       }
                        data.terminated = 1;
                        data.data = &data.buffer -> data [0];
                        strcpy ((char *)data.buffer -> data, val);
                } else if (token == NUMBER_OR_NAME || token == NUMBER) {
                        memset (&data, 0, sizeof data);
-                       if (!parse_cshl (&data, cfile))
-                               return (struct class *)0;
+                       if (!parse_cshl (&data, cfile)) {
+                               class_dereference (&pc, MDL);
+                       }
+                               return 0;
                } else {
                        parse_warn (cfile, "Expecting string or hex list.");
-                       return (struct class *)0;
+                       class_dereference (&pc, MDL);
+                       return 0;
                }
        }
 
        /* See if there's already a class in the hash table matching the
           hash data. */
        if (type == 0 || type == 1 || type == 3)
-               class = ((struct class *)
-                        hash_lookup (pc -> hash, data.data, data.len));
+               class_hash_lookup (&class, pc -> hash,
+                                  (const char *)data.data, data.len, MDL);
 
        /* If we didn't find an existing class, allocate a new one. */
        if (!class) {
                /* Allocate the class structure... */
-               class = (struct class *)dmalloc (sizeof (struct class), MDL);
-               if (!class)
-                       log_fatal ("No memory for class %s.", val);
-               memset (class, 0, sizeof *class);
+               status = class_allocate (&class, MDL);
                if (pc) {
-                       class -> group = pc -> group;
-                       class -> superclass = pc;
+                       group_reference (&class -> group, pc -> group, MDL);
+                       class_reference (&class -> superclass, pc, MDL);
                        class -> lease_limit = pc -> lease_limit;
                        if (class -> lease_limit) {
                                class -> billed_leases =
@@ -1587,26 +1639,27 @@ struct class *parse_class_declaration (cfile, group, type)
                        }
                        data_string_copy (&class -> hash_string, &data, MDL);
                        if (!pc -> hash)
-                               pc -> hash = new_hash (0, 0, 0);
+                               pc -> hash =
+                                       new_hash ((hash_reference)
+                                                 omapi_object_reference,
+                                                 (hash_dereference)
+                                                 omapi_object_dereference, 0);
                        add_hash (pc -> hash,
                                  class -> hash_string.data,
                                  class -> hash_string.len,
-                                 (unsigned char *)class);
+                                 (void *)class, MDL);
                } else {
-                       class -> group =
-                               clone_group (group, MDL);
+                       if (!clone_group (&class -> group, group, MDL))
+                               log_fatal ("no memory to clone class group.");
                }
 
                /* If this is an implicit vendor or user class, add a
                   statement that causes the vendor or user class ID to
                   be sent back in the reply. */
                if (type == 0 || type == 1) {
-                       stmt = ((struct executable_statement *)
-                               dmalloc (sizeof (struct executable_statement),
-                                        MDL));
-                       if (!stmt)
+                       stmt = (struct executable_statement *)0;
+                       if (!executable_statement_allocate (&stmt, MDL))
                                log_fatal ("no memory for class statement.");
-                       memset (stmt, 0, sizeof *stmt);
                        stmt -> op = supersede_option_statement;
                        if (option_cache_allocate (&stmt -> data.option,
                                                   MDL)) {
@@ -1627,19 +1680,26 @@ struct class *parse_class_declaration (cfile, group, type)
        if (type == 0 || type == 1 || type == 3)
                data_string_forget (&data, MDL);
 
-       /* Spawned classes don't have their own settings. */
+       /* Spawned classes don't have to have their own settings. */
        if (class -> superclass) {
                token = peek_token (&val, cfile);
                if (token == SEMI) {
                        next_token (&val, cfile);
-                       return class;
+                       if (cp)
+                               status = class_reference (cp, class, MDL);
+                       class_dereference (&class, MDL);
+                       return cp ? (status == ISC_R_SUCCESS) : 1;
                }
                /* Give the subclass its own group. */
-               class -> group = clone_group (class -> group, MDL);
+               clone_group (&class -> group, class -> group, MDL);
        }
 
-       if (!parse_lbrace (cfile))
-               return (struct class *)0;
+       if (!parse_lbrace (cfile)) {
+               class_dereference (&class, MDL);
+               if (pc)
+                       class_dereference (&pc, MDL);
+               return 0;
+       }
 
        do {
                token = peek_token (&val, cfile);
@@ -1744,16 +1804,21 @@ struct class *parse_class_declaration (cfile, group, type)
        } while (1);
        if (type == 2 && new) {
                if (!collections -> classes)
-                       collections -> classes = class;
+                       class_reference (&collections -> classes, class, MDL);
                else {
-                       struct class *cp;
-                       for (cp = collections -> classes;
-                            cp -> nic; cp = cp -> nic)
+                       struct class *c;
+                       for (c = collections -> classes;
+                            c -> nic; c = c -> nic)
                                ;
-                       cp -> nic = class;
+                       class_reference (&c -> nic, class, MDL);
                }
        }
-       return class;
+       if (cp)
+               status = class_reference (cp, class, MDL);
+       class_dereference (&class, MDL);
+       if (pc)
+               class_dereference (&pc, MDL);
+       return cp ? (status == ISC_R_SUCCESS) : 1;
 }
 
 /* shared-network-declaration :==
@@ -1768,15 +1833,16 @@ void parse_shared_net_declaration (cfile, group)
        struct shared_network *share;
        char *name;
        int declaration = 0;
+       isc_result_t status;
 
-       share = new_shared_network (MDL);
-       if (!share)
-               log_fatal ("No memory for shared subnet");
-       share -> pools = (struct pool *)0;
-       share -> next = (struct shared_network *)0;
-       share -> interface = (struct interface_info *)0;
-       share -> group = clone_group (group, MDL);
-       share -> group -> shared_network = share;
+       share = (struct shared_network *)0;
+       status = shared_network_allocate (&share, MDL);
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Can't allocate shared subnet: %s",
+                          isc_result_totext (status));
+       clone_group (&share -> group, group, MDL);
+       shared_network_reference (&share -> group -> shared_network,
+                                 share, MDL);
 
        /* Get the name of the shared network... */
        token = peek_token (&val, cfile);
@@ -1793,24 +1859,28 @@ void parse_shared_net_declaration (cfile, group)
                strcpy (name, val);
        } else {
                name = parse_host_name (cfile);
-               if (!name)
+               if (!name) {
+                       shared_network_dereference (&share, MDL);
                        return;
+               }
        }
        share -> name = name;
 
-       if (!parse_lbrace (cfile))
+       if (!parse_lbrace (cfile)) {
+               shared_network_dereference (&share, MDL);
                return;
+       }
 
        do {
                token = peek_token (&val, cfile);
                if (token == RBRACE) {
                        token = next_token (&val, cfile);
-                       if (!share -> subnets) {
+                       if (!share -> subnets)
                                parse_warn (cfile,
                                            "empty shared-network decl");
-                               return;
-                       }
-                       enter_shared_network (share);
+                       else
+                               enter_shared_network (share);
+                       shared_network_dereference (&share, MDL);
                        return;
                } else if (token == EOF) {
                        token = next_token (&val, cfile);
@@ -1830,6 +1900,7 @@ void parse_shared_net_declaration (cfile, group)
                                               (struct host_decl *)0,
                                               declaration);
        } while (1);
+       shared_network_dereference (&share, MDL);
 }
 
 /* subnet-declaration :==
@@ -1847,17 +1918,23 @@ void parse_subnet_declaration (cfile, share)
        unsigned len = sizeof addr;
        int declaration = 0;
        struct interface_info *ip;
+       isc_result_t status;
 
-       subnet = new_subnet (MDL);
-       if (!subnet)
-               log_fatal ("No memory for new subnet");
-       subnet -> shared_network = share;
-       subnet -> group = clone_group (share -> group, MDL);
-       subnet -> group -> subnet = subnet;
+       subnet = (struct subnet *)0;
+       status = subnet_allocate (&subnet, MDL);
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Allocation of new subnet failed: %s",
+                          isc_result_totext (status));
+       shared_network_reference (&subnet -> shared_network, share, MDL);
+       if (!clone_group (&subnet -> group, share -> group, MDL))
+               log_fatal ("allocation of group for new subnet failed.");
+       subnet_reference (&subnet -> group -> subnet, subnet, MDL);
 
        /* Get the network number... */
-       if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
+       if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
+               subnet_dereference (&subnet, MDL);
                return;
+       }
        memcpy (iaddr.iabuf, addr, len);
        iaddr.len = len;
        subnet -> net = iaddr;
@@ -1870,16 +1947,30 @@ void parse_subnet_declaration (cfile, share)
        }
 
        /* Get the netmask... */
-       if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
+       if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
+               subnet_dereference (&subnet, MDL);
                return;
+       }
        memcpy (iaddr.iabuf, addr, len);
        iaddr.len = len;
        subnet -> netmask = iaddr;
 
+       /* Validate the network number/netmask pair. */
+       if (host_addr (subnet -> net, subnet -> netmask)) {
+               parse_warn (cfile,
+                           "subnet %s: bad subnet number/mask combination.",
+                           piaddr (subnet -> net));
+               subnet_dereference (&subnet, MDL);
+               skip_to_semi (cfile);
+               return;
+       }
+
        enter_subnet (subnet);
 
-       if (!parse_lbrace (cfile))
+       if (!parse_lbrace (cfile)) {
+               subnet_dereference (&subnet, MDL);
                return;
+       }
 
        do {
                token = peek_token (&val, cfile);
@@ -1906,23 +1997,33 @@ void parse_subnet_declaration (cfile, share)
 
        /* Add the subnet to the list of subnets in this shared net. */
        if (!share -> subnets)
-               share -> subnets = subnet;
+               subnet_reference (&share -> subnets, subnet, MDL);
        else {
                u = (struct subnet *)0;
                for (t = share -> subnets;
                     t -> next_sibling; t = t -> next_sibling) {
                        if (subnet_inner_than (subnet, t, 0)) {
-                               if (u)
-                                       u -> next_sibling = subnet;
-                               else
-                                       share -> subnets = subnet;
-                               subnet -> next_sibling = t;
+                               subnet_reference (&subnet -> next_sibling,
+                                                 t, MDL);
+                               if (u) {
+                                       subnet_dereference (&u -> next_sibling,
+                                                           MDL);
+                                       subnet_reference (&u -> next_sibling,
+                                                         subnet, MDL);
+                               } else {
+                                       subnet_dereference (&share -> subnets,
+                                                           MDL);
+                                       subnet_reference (&share -> subnets,
+                                                         subnet, MDL);
+                               }
+                               subnet_dereference (&subnet, MDL);
                                return;
                        }
                        u = t;
                }
-               t -> next_sibling = subnet;
+               subnet_reference (&t -> next_sibling, subnet, MDL);
        }
+       subnet_dereference (&subnet, MDL);
 }
 
 /* group-declaration :== RBRACE parameters declarations LBRACE */
@@ -1942,7 +2043,9 @@ void parse_group_declaration (cfile, group)
        int dynamicp = 0;
        int staticp = 0;
 
-       g = clone_group (group, MDL);
+       g = (struct group *)0;
+       if (!clone_group (&g, group, MDL))
+               log_fatal ("no memory for explicit group.");
 
        token = peek_token (&val, cfile);
        if (is_identifier (token) || token == STRING) {
@@ -1954,8 +2057,10 @@ void parse_group_declaration (cfile, group)
                strcpy (name, val);
        }               
 
-       if (!parse_lbrace (cfile))
+       if (!parse_lbrace (cfile)) {
+               group_dereference (&g, MDL);
                return;
+       }
 
        do {
                token = peek_token (&val, cfile);
@@ -1987,27 +2092,28 @@ void parse_group_declaration (cfile, group)
        if (name) {
                if (deletedp) {
                        if (group_name_hash) {
-                               t = ((struct group_object *)
-                                    hash_lookup (group_name_hash,
-                                                 (unsigned char *)name,
-                                                 strlen (name)));
-                               if (t) {
+                               t = (struct group_object *)0;
+                               if (group_hash_lookup (&t, group_name_hash,
+                                                      name,
+                                                      strlen (name), MDL)) {
                                        delete_group (t, 0);
                                }
                        }
                } else {
-                       t = dmalloc (sizeof *t, MDL);
-                       if (!t)
-                               log_fatal ("no memory for group decl %s", val);
-                       memset (t, 0, sizeof *t);
-                       t -> type = dhcp_type_group;
-                       t -> group = g;
+                       t = (struct group_object *)0;
+                       status = group_object_allocate (&t, MDL);
+                       if (status != ISC_R_SUCCESS)
+                               log_fatal ("no memory for group decl %s: %s",
+                                          val, isc_result_totext (status));
+                       group_reference (&t -> group, g, MDL);
                        t -> name = name;
                        t -> flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
                                      (dynamicp ? GROUP_OBJECT_DYNAMIC : 0) |
                                      (deletedp ? GROUP_OBJECT_DELETED : 0));
                        supersede_group (t, 0);
                }
+               if (t)
+                       group_object_dereference (&t, MDL);
        }
 }
 
@@ -2090,8 +2196,7 @@ TIME parse_timestamp (cfile)
                     | CLASS identifier SEMI
                     | DYNAMIC_BOOTP SEMI */
 
-struct lease *parse_lease_declaration (cfile)
-       struct parse *cfile;
+int parse_lease_declaration (struct lease **lp, struct parse *cfile)
 {
        const char *val;
        enum dhcp_token token;
@@ -2100,7 +2205,7 @@ struct lease *parse_lease_declaration (cfile)
        int seenmask = 0;
        int seenbit;
        char tbuf [32];
-       static struct lease lease;
+       struct lease *lease;
        struct executable_statement *on;
        struct expression *exp;
        struct data_string ds;
@@ -2109,18 +2214,25 @@ struct lease *parse_lease_declaration (cfile)
        char *s;
        int noequal, newbinding;
        struct binding *binding;
+       isc_result_t status;
 
-       /* Zap the lease structure... */
-       memset (&lease, 0, sizeof lease);
+       lease = (struct lease *)0;
+       status = lease_allocate (&lease, MDL);
+       if (status != ISC_R_SUCCESS)
+               return 0;
 
        /* Get the address for which the lease has been issued. */
-       if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
-               return (struct lease *)0;
-       memcpy (lease.ip_addr.iabuf, addr, len);
-       lease.ip_addr.len = len;
+       if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
+               lease_dereference (&lease, MDL);
+               return 0;
+       }
+       memcpy (lease -> ip_addr.iabuf, addr, len);
+       lease -> ip_addr.len = len;
 
-       if (!parse_lbrace (cfile))
-               return (struct lease *)0;
+       if (!parse_lbrace (cfile)) {
+               lease_dereference (&lease, MDL);
+               return 0;
+       }
 
        do {
                token = next_token (&val, cfile);
@@ -2145,32 +2257,32 @@ struct lease *parse_lease_declaration (cfile)
                        switch (token) {
                              case STARTS:
                                seenbit = 1;
-                               lease.starts = t;
+                               lease -> starts = t;
                                break;
                        
                              case ENDS:
                                seenbit = 2;
-                               lease.ends = t;
+                               lease -> ends = t;
                                break;
                                
                              case TIMESTAMP:
                                seenbit = 4;
-                               lease.timestamp = t;
+                               lease -> timestamp = t;
                                break;
 
                              case TSTP:
                                seenbit = 65536;
-                               lease.tstp = t;
+                               lease -> tstp = t;
                                break;
                                
                              case TSFP:
                                seenbit = 131072;
-                               lease.tsfp = t;
+                               lease -> tsfp = t;
                                break;
                                
                              case CLTT:
                                seenbit = 524288;
-                               lease.cltt = t;
+                               lease -> cltt = t;
                                break;
                                
                              default: /* for gcc, we'll never get here. */
@@ -2185,24 +2297,28 @@ struct lease *parse_lease_declaration (cfile)
                        if (token == STRING) {
                                unsigned char *tuid;
                                token = next_token (&val, cfile);
-                               lease.uid_len = strlen (val);
+                               lease -> uid_len = strlen (val);
                                tuid = ((unsigned char *)
-                                       dmalloc (lease.uid_len, MDL));
+                                       dmalloc (lease -> uid_len, MDL));
                                if (!tuid) {
                                        log_error ("no space for uid");
-                                       return (struct lease *)0;
+                                       lease_dereference (&lease, MDL);
+                                       return 0;
                                }
-                               memcpy (tuid, val, lease.uid_len);
-                               lease.uid = tuid;
+                               memcpy (tuid, val, lease -> uid_len);
+                               lease -> uid = tuid;
                        } else {
-                               lease.uid_len = 0;
-                               lease.uid = (parse_numeric_aggregate
-                                            (cfile, (unsigned char *)0,
-                                             &lease.uid_len, ':', 16, 8));
-                               if (!lease.uid)
-                                       return (struct lease *)0;
-                               if (lease.uid_len == 0) {
-                                       lease.uid = (unsigned char *)0;
+                               lease -> uid_len = 0;
+                               lease -> uid = (parse_numeric_aggregate
+                                               (cfile, (unsigned char *)0,
+                                                &lease -> uid_len, ':',
+                                                16, 8));
+                               if (!lease -> uid) {
+                                       lease_dereference (&lease, MDL);
+                                       return 0;
+                               }
+                               if (lease -> uid_len == 0) {
+                                       lease -> uid = (unsigned char *)0;
                                        parse_warn (cfile, "zero-length uid");
                                        seenbit = 0;
                                        parse_semi (cfile);
@@ -2210,7 +2326,7 @@ struct lease *parse_lease_declaration (cfile)
                                }
                        }
                        parse_semi (cfile);
-                       if (!lease.uid) {
+                       if (!lease -> uid) {
                                log_fatal ("No memory for lease uid");
                        }
                        break;
@@ -2221,7 +2337,8 @@ struct lease *parse_lease_declaration (cfile)
                        if (!is_identifier (token)) {
                                if (token != SEMI)
                                        skip_to_rbrace (cfile, 1);
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                        parse_semi (cfile);
                        /* for now, we aren't using this. */
@@ -2230,12 +2347,12 @@ struct lease *parse_lease_declaration (cfile)
                      case HARDWARE:
                        seenbit = 64;
                        parse_hardware_param (cfile,
-                                             &lease.hardware_addr);
+                                             &lease -> hardware_addr);
                        break;
 
                      case DYNAMIC_BOOTP:
                        seenbit = 128;
-                       lease.flags |= BOOTP_LEASE;
+                       lease -> flags |= BOOTP_LEASE;
                        parse_semi (cfile);
                        break;
                        
@@ -2244,22 +2361,24 @@ struct lease *parse_lease_declaration (cfile)
                        if (token != IS) {
                                parse_warn (cfile, "expecting \"is\".");
                                skip_to_rbrace (cfile, 1);
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                        token = next_token (&val, cfile);
                        if (token != OWNER) {
                                parse_warn (cfile, "expecting \"owner\".");
                                skip_to_rbrace (cfile, 1);
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                        seenbit = 262144;
-                       lease.flags |= PEER_IS_OWNER;
+                       lease -> flags |= PEER_IS_OWNER;
                        parse_semi (cfile);
                        break;
 
                      case ABANDONED:
                        seenbit = 256;
-                       lease.flags |= ABANDONED_LEASE;
+                       lease -> flags |= ABANDONED_LEASE;
                        parse_semi (cfile);
                        break;
 
@@ -2267,15 +2386,15 @@ struct lease *parse_lease_declaration (cfile)
                        seenbit = 512;
                        token = peek_token (&val, cfile);
                        if (token == STRING)
-                               lease.hostname = parse_string (cfile);
+                               lease -> hostname = parse_string (cfile);
                        else {
-                               lease.hostname = parse_host_name (cfile);
-                               if (lease.hostname)
+                               lease -> hostname = parse_host_name (cfile);
+                               if (lease -> hostname)
                                        parse_semi (cfile);
                        }
-                       if (!lease.hostname) {
+                       if (!lease -> hostname) {
                                seenbit = 0;
-                               return (struct lease *)0;
+                               return 0;
                        }
                        break;
                        
@@ -2283,16 +2402,18 @@ struct lease *parse_lease_declaration (cfile)
                        seenbit = 1024;
                        token = peek_token (&val, cfile);
                        if (token == STRING)
-                               lease.client_hostname = parse_string (cfile);
+                               lease -> client_hostname =
+                                       parse_string (cfile);
                        else {
-                               lease.client_hostname =
+                               lease -> client_hostname =
                                        parse_host_name (cfile);
-                               if (lease.client_hostname)
+                               if (lease -> client_hostname)
                                        parse_semi (cfile);
                        }
-                       if (!lease.client_hostname) {
+                       if (!lease -> client_hostname) {
                                seenbit = 0;
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                        break;
                        
@@ -2308,15 +2429,18 @@ struct lease *parse_lease_declaration (cfile)
                                        token = BILLING;
                                        break;
                                }
-                               lease.billing_class = find_class (val);
-                               if (!lease.billing_class)
+                               find_class (&lease -> billing_class, val, MDL);
+                               if (!lease -> billing_class)
                                        parse_warn (cfile,
                                                    "unknown class %s", val);
                                parse_semi (cfile);
                        } else if (token == SUBCLASS) {
-                               lease.billing_class =
-                                       (parse_class_declaration
-                                        (cfile, (struct group *)0, 3));
+                               if (lease -> billing_class)
+                                       class_dereference
+                                               (&lease -> billing_class, MDL);
+                               parse_class_declaration
+                                       (&lease -> billing_class,
+                                        cfile, (struct group *)0, 3);
                        } else {
                                parse_warn (cfile, "expecting \"class\"");
                                if (token != SEMI)
@@ -2329,21 +2453,22 @@ struct lease *parse_lease_declaration (cfile)
                        lose = 0;
                        if (!parse_on_statement (&on, cfile, &lose)) {
                                skip_to_rbrace (cfile, 1);
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                        seenbit = 0;
                        if ((on -> data.on.evtypes & ON_EXPIRY) &&
                            on -> data.on.statements) {
                                seenbit |= 16384;
                                executable_statement_reference
-                                       (&lease.on_expiry,
+                                       (&lease -> on_expiry,
                                         on -> data.on.statements, MDL);
                        }
                        if ((on -> data.on.evtypes & ON_RELEASE) &&
                            on -> data.on.statements) {
                                seenbit |= 32768;
                                executable_statement_reference
-                                       (&lease.on_release,
+                                       (&lease -> on_release,
                                         on -> data.on.statements, MDL);
                        }
                        executable_statement_dereference (&on, MDL);
@@ -2359,12 +2484,13 @@ struct lease *parse_lease_declaration (cfile)
                                            val);
                              badset:
                                skip_to_semi (cfile);
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                        
                        seenbit = 0;
                      special_set:
-                       binding = find_binding (&lease.scope, val);
+                       binding = find_binding (&lease -> scope, val);
                        if (!binding) {
                                binding = dmalloc (sizeof *binding, MDL);
                                if (!binding)
@@ -2422,7 +2548,8 @@ struct lease *parse_lease_declaration (cfile)
                            if (!s) {
                                    binding_value_dereference
                                            (&binding -> value, MDL);
-                                   return (struct lease *)0;
+                                   lease_dereference (&lease, MDL);
+                                   return 0;
                            }
                            if (binding -> value -> value.data.len) {
                                if (!(buffer_allocate
@@ -2447,7 +2574,8 @@ struct lease *parse_lease_declaration (cfile)
                                            skip_to_semi (cfile);
                                    binding_value_dereference
                                            (&binding -> value, MDL);
-                                   return (struct lease *)0;
+                                   lease_dereference (&lease, MDL);
+                                   return 0;
                            }
                            binding -> value -> type = binding_numeric;
                            binding -> value -> value.intval = atol (val);
@@ -2467,12 +2595,13 @@ struct lease *parse_lease_declaration (cfile)
                                skip_to_semi (cfile);
                                binding_value_dereference (&binding -> value,
                                                           MDL);
-                               return (struct lease *)0;
+                               lease_dereference (&lease, MDL);
+                               return 0;
                        }
                                
                        if (newbinding) {
-                               binding -> next = lease.scope.bindings;
-                               lease.scope.bindings = binding;
+                               binding -> next = lease -> scope.bindings;
+                               lease -> scope.bindings = binding;
                        }
                        parse_semi (cfile);
                        break;
@@ -2489,28 +2618,31 @@ struct lease *parse_lease_declaration (cfile)
                        }
                        skip_to_semi (cfile);
                        seenbit = 0;
-                       return (struct lease *)0;
+                       lease_dereference (&lease, MDL);
+                       return 0;
                }
 
                if (seenmask & seenbit) {
                        parse_warn (cfile,
                                    "Too many %s parameters in lease %s\n",
-                                   tbuf, piaddr (lease.ip_addr));
+                                   tbuf, piaddr (lease -> ip_addr));
                } else
                        seenmask |= seenbit;
 
        } while (1);
-       return &lease;
+       lease_reference (lp, lease, MDL);
+       lease_dereference (&lease, MDL);
+       return 1;
 }
 
 /* address-range-declaration :== ip-address ip-address SEMI
                               | DYNAMIC_BOOTP ip-address ip-address SEMI */
 
-void parse_address_range (cfile, group, type, pool)
+void parse_address_range (cfile, group, type, inpool)
        struct parse *cfile;
        struct group *group;
        int type;
-       struct pool *pool;
+       struct pool *inpool;
 {
        struct iaddr low, high, net;
        unsigned char addr [4];
@@ -2521,6 +2653,8 @@ void parse_address_range (cfile, group, type, pool)
        struct subnet *subnet;
        struct shared_network *share;
        struct pool *p;
+       struct pool *pool;
+       isc_result_t status;
 
        if ((token = peek_token (&val, cfile)) == DYNAMIC_BOOTP) {
                token = next_token (&val, cfile);
@@ -2572,7 +2706,7 @@ void parse_address_range (cfile, group, type, pool)
                }
        }
 
-       if (!pool) {
+       if (!inpool) {
                struct pool *last;
 
                /* If we're permitting dynamic bootp for this range,
@@ -2597,9 +2731,10 @@ void parse_address_range (cfile, group, type, pool)
                /* If we didn't get a pool, make one. */
                if (!pool) {
                        struct permit *p;
-                       pool = new_pool (MDL);
-                       if (!pool)
-                               log_fatal ("no memory for ad-hoc pool.");
+                       status = pool_allocate (&pool, MDL);
+                       if (status != ISC_R_SUCCESS)
+                               log_fatal ("no memory for ad-hoc pool: %s",
+                                          isc_result_totext (status));
                        p = new_permit (MDL);
                        if (!p)
                                log_fatal ("no memory for ad-hoc permit.");
@@ -2615,14 +2750,18 @@ void parse_address_range (cfile, group, type, pool)
                        }
 
                        if (share -> pools)
-                               last -> next = pool;
+                               pool_reference (&last -> next, pool, MDL);
                        else
-                               share -> pools = pool;
-                       pool -> shared_network = share;
-                       pool -> group = clone_group (share -> group, MDL);
+                               pool_reference (&share -> pools, pool, MDL);
+                       shared_network_reference (&pool -> shared_network,
+                                                 share, MDL);
+                       if (!clone_group (&pool -> group, share -> group, MDL))
+                               log_fatal ("no memory for anon pool group.");
                }
 
-       }
+       } else
+               pool_reference (&pool, inpool, MDL);
+
 #if defined (FAILOVER_PROTOCOL)
        if (pool -> failover_peer && dynamic) {
                /* Doctor, do you think I'm overly sensitive
@@ -2650,6 +2789,7 @@ void parse_address_range (cfile, group, type, pool)
 
        /* Create the new address range... */
        new_address_range (low, high, subnet, pool);
+       pool_dereference (&pool, MDL);
 }
 
 /* allow-deny-keyword :== BOOTP
index 488c670a6589876697ff391036f1076224d60428..da252c5fcddbd8bacc5ad1ab8900742bb3d81dcc 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: db.c,v 1.49 2000/05/04 18:58:12 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: db.c,v 1.50 2000/05/16 23:03:39 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -431,7 +431,7 @@ int write_host (host)
                if (host -> group &&
                    (!host -> named_group ||
                     host -> group != host -> named_group -> group) &&
-                   host -> group != &root_group) {
+                   host -> group != root_group) {
                        errno = 0;
                        write_statements (db_file,
                                          host -> group -> statements, 8);
@@ -732,3 +732,12 @@ void new_lease_file ()
 
        counting = 1;
 }
+
+int group_writer (struct group_object *group)
+{
+       if (!write_group (group))
+               return 0;
+       if (!commit_leases ())
+               return 0;
+       return 1;
+}
index afb982cf8a96b741f664a9e9aa13da21c9ce304e..f8d5b8bf54904e55bb7d6d4bd940ec3a99388c90 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: dhcp.c,v 1.148 2000/05/04 18:58:13 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: dhcp.c,v 1.149 2000/05/16 23:03:42 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -104,7 +104,7 @@ void dhcpdiscover (packet, ms_nulltp)
        struct packet *packet;
        int ms_nulltp;
 {
-       struct lease *lease;
+       struct lease *lease = (struct lease *)0;
        char msgbuf [1024]; /* XXX */
        TIME when;
        char *s;
@@ -114,7 +114,7 @@ void dhcpdiscover (packet, ms_nulltp)
        dhcp_failover_state_t *peer;
 #endif
 
-       lease = find_lease (packet, packet -> shared_network, 0);
+       find_lease (&lease, packet, packet -> shared_network, 0, MDL);
 
        if (lease && lease -> client_hostname &&
            db_printable (lease -> client_hostname))
@@ -145,7 +145,7 @@ void dhcpdiscover (packet, ms_nulltp)
                    peer -> my_state == normal) {
                        log_info ("%s: letting peer %s respond.",
                                  msgbuf, peer -> name);
-                       return;
+                       goto out;
                }
        }
 #endif
@@ -154,15 +154,14 @@ void dhcpdiscover (packet, ms_nulltp)
        if (!packet -> shared_network) {
                log_info ("Packet from unknown subnet: %s",
                      inet_ntoa (packet -> raw -> giaddr));
-               return;
+               goto out;
        }
 
        /* If we didn't find a lease, try to allocate one... */
        if (!lease) {
-               lease = allocate_lease (packet,
-                                       packet -> shared_network -> pools, 
-                                       0, &peer_has_leases);
-               if (!lease) {
+               if (!allocate_lease (&lease, packet,
+                                    packet -> shared_network -> pools, 
+                                    &peer_has_leases)) {
                        if (peer_has_leases)
                                log_info ("%s: peer holds all free leases",
                                          msgbuf);
@@ -196,7 +195,7 @@ void dhcpdiscover (packet, ms_nulltp)
                        if (!load_balance_mine (packet, peer)) {
                                log_debug ("%s: load balance to peer %s",
                                           msgbuf, peer -> name);
-                               return;
+                               goto out;
                        }
                }
        }
@@ -213,6 +212,9 @@ void dhcpdiscover (packet, ms_nulltp)
                when = lease -> ends;
 
        ack_lease (packet, lease, DHCPOFFER, when, msgbuf, ms_nulltp);
+      out:
+       if (lease)
+               lease_dereference (&lease, MDL);
 }
 
 void dhcprequest (packet, ms_nulltp)
@@ -244,15 +246,15 @@ void dhcprequest (packet, ms_nulltp)
                cip.len = 4;
                memcpy (cip.iabuf, &packet -> raw -> ciaddr.s_addr, 4);
        }
-       subnet = find_subnet (cip);
 
        /* Find the lease that matches the address requested by the
           client. */
 
-       if (subnet)
-               lease = find_lease (packet, subnet -> shared_network, &ours);
-       else
-               lease = (struct lease *)0;
+       subnet = (struct subnet *)0;
+       lease = (struct lease *)0;
+       if (find_subnet (&subnet, cip, MDL))
+               find_lease (&lease, packet,
+                           subnet -> shared_network, &ours, MDL);
 
        if (lease && lease -> client_hostname &&
            db_printable (lease -> client_hostname))
@@ -338,13 +340,15 @@ void dhcprequest (packet, ms_nulltp)
                        }
                        /* Otherwise, ignore it. */
                        log_info ("%s: ignored (not authoritative).", msgbuf);
-                       return;
+                       goto out;
                }
 
                /* If we do know where it came from and it asked for an
                   address that is not on that shared network, nak it. */
-               subnet = find_grouped_subnet (packet -> shared_network, cip);
-               if (!subnet) {
+               if (subnet)
+                       subnet_dereference (&subnet, MDL);
+               if (!find_grouped_subnet (&subnet, packet -> shared_network,
+                                         cip, MDL)) {
                        if (packet -> shared_network -> group -> authoritative)
                        {
                                log_info ("%s: wrong network.", msgbuf);
@@ -364,7 +368,7 @@ void dhcprequest (packet, ms_nulltp)
            lookup_option (&dhcp_universe, packet -> options,
                           DHO_DHCP_SERVER_IDENTIFIER)) {
                log_info ("%s: ignored (not for me)", msgbuf);
-               return;
+               goto out;
        }
 
        /* If we found a lease, but it belongs to a failover peer, and
@@ -381,7 +385,7 @@ void dhcprequest (packet, ms_nulltp)
            lease -> pool && lease -> pool -> failover_peer &&
            lease -> pool -> failover_peer -> my_state == normal) {
                log_info ("%s: ignored (not for me)", msgbuf);
-               return;
+               goto out;
        }
 #endif /* FAILOVER_PROTOCOL */
 
@@ -390,7 +394,7 @@ void dhcprequest (packet, ms_nulltp)
        if (!lease && ours) {
                log_info ("%s: lease %s unavailable.", msgbuf, piaddr (cip));
                nak_lease (packet, &cip);
-               return;
+               goto out;
        }
 
        /* Otherwise, send the lease to the client if we found one. */
@@ -398,13 +402,20 @@ void dhcprequest (packet, ms_nulltp)
                ack_lease (packet, lease, DHCPACK, 0, msgbuf, ms_nulltp);
        } else
                log_info ("%s: unknown lease %s.", msgbuf, piaddr (cip));
+
+      out:
+       if (subnet)
+               subnet_dereference (&subnet, MDL);
+       if (lease)
+               lease_dereference (&lease, MDL);
+       return;
 }
 
 void dhcprelease (packet, ms_nulltp)
        struct packet *packet;
        int ms_nulltp;
 {
-       struct lease *lease;
+       struct lease *lease = (struct lease *)0;
        struct iaddr cip;
        struct option_cache *oc;
        struct data_string data;
@@ -428,7 +439,7 @@ void dhcprelease (packet, ms_nulltp)
            evaluate_option_cache (&data, packet, (struct lease *)0,
                                   packet -> options, (struct option_state *)0,
                                   &global_scope, oc, MDL)) {
-               lease = find_lease_by_uid (data.data, data.len);
+               find_lease_by_uid (&lease, data.data, data.len, MDL);
                data_string_forget (&data, MDL);
 
                /* See if we can find a lease that matches the IP address
@@ -439,8 +450,7 @@ void dhcprelease (packet, ms_nulltp)
                                break;
                        }
                }
-       } else
-               lease = (struct lease *)0;
+       }
 
        /* The client is supposed to pass a valid client-identifier,
           but the spec on this has changed historically, so try the
@@ -448,7 +458,7 @@ void dhcprelease (packet, ms_nulltp)
        if (!lease) {
                cip.len = 4;
                memcpy (cip.iabuf, &packet -> raw -> ciaddr, 4);
-               lease = find_lease_by_ip_addr (cip);
+               find_lease_by_ip_addr (&lease, cip, MDL);
        }
 
 
@@ -476,15 +486,17 @@ void dhcprelease (packet, ms_nulltp)
                  lease ? "" : "not ");
 
        /* If we found a lease, release it. */
-       if (lease && lease -> ends > cur_time)
+       if (lease && lease -> ends > cur_time) {
                release_lease (lease, packet);
+               lease_dereference (&lease, MDL);
+       }
 }
 
 void dhcpdecline (packet, ms_nulltp)
        struct packet *packet;
        int ms_nulltp;
 {
-       struct lease *lease;
+       struct lease *lease = (struct lease *)0;
        struct iaddr cip;
        struct option_cache *oc;
        struct data_string data;
@@ -508,7 +520,7 @@ void dhcpdecline (packet, ms_nulltp)
        cip.len = 4;
        memcpy (cip.iabuf, data.data, 4);
        data_string_forget (&data, MDL);
-       lease = find_lease_by_ip_addr (cip);
+       find_lease_by_ip_addr (&lease, cip, MDL);
 
        option_state_allocate (&options, MDL);
 
@@ -569,6 +581,8 @@ void dhcpdecline (packet, ms_nulltp)
        }
                
        option_state_dereference (&options, MDL);
+       if (lease)
+               lease_dereference (&lease, MDL);
 }
 
 void dhcpinform (packet, ms_nulltp)
@@ -583,7 +597,7 @@ void dhcpinform (packet, ms_nulltp)
        struct dhcp_packet raw;
        struct packet outgoing;
        unsigned char dhcpack = DHCPACK;
-       struct subnet *subnet;
+       struct subnet *subnet = (struct subnet *)0;
        struct iaddr cip;
        unsigned i, j;
        int nulltp;
@@ -612,7 +626,7 @@ void dhcpinform (packet, ms_nulltp)
 
        /* Find the subnet that the client is on. */
        oc = (struct option_cache *)0;
-       subnet = find_subnet (cip);
+       find_subnet (&subnet , cip, MDL);
 
        /* Sourceless packets don't make sense here. */
        if (!subnet) {
@@ -625,8 +639,23 @@ void dhcpinform (packet, ms_nulltp)
           there's overhead involved in checking this, so let's see how people
           react first. */
        if (subnet && !subnet -> group -> authoritative) {
+               static int eso = 0;
                log_info ("%s: not authoritative for subnet %s",
                          msgbuf, piaddr (subnet -> net));
+               if (!eso) {
+                       log_info ("If this DHCP server is authoritative for%s",
+                                 " that subnet,");
+                       log_info ("please write an `authoritative;' directi%s",
+                                 "ve either in the");
+                       log_info ("subnet declaration or in some scope that%s",
+                                 "encloses the");
+                       log_info ("subnet declaration - for example, write %s",
+                                 "it at the top");
+                       log_info ("of the dhcpd.conf file.");
+               }
+               if (eso++ == 100)
+                       eso = 0;
+               subnet_dereference (&subnet, MDL);
                return;
        }
 
@@ -801,13 +830,14 @@ void dhcpinform (packet, ms_nulltp)
            evaluate_option_cache (&d1, packet, (struct lease *)0,
                                   packet -> options, options,
                                   &global_scope, oc, MDL)) {
-               const struct universe *u;
+               struct universe *u = (struct universe *)0;
                
-               u = ((const struct universe *)
-                    hash_lookup (universe_hash, d1.data, d1.len));
-               if (!u) {
+               if (!universe_hash_lookup (&u, universe_hash,
+                                          d1.data, d1.len, MDL)) {
                        log_error ("unknown option space %s.", d1.data);
                        option_state_dereference (&options, MDL);
+                       if (subnet)
+                               subnet_dereference (&subnet, MDL);
                        return;
                }
 
@@ -909,6 +939,8 @@ void dhcpinform (packet, ms_nulltp)
                      ? fallback_interface : packet -> interface),
                     &outgoing, &raw, outgoing.packet_length,
                     from, &to, (struct hardware *)0);
+       if (subnet)
+               subnet_dereference (&subnet, MDL);
 }
 
 void nak_lease (packet, cip)
@@ -922,11 +954,12 @@ void nak_lease (packet, cip)
        unsigned char nak = DHCPNAK;
        struct packet outgoing;
        struct hardware hto;
-       int i;
+       unsigned i;
        struct data_string data;
        struct option_state *options = (struct option_state *)0;
        struct expression *expr;
        struct option_cache *oc = (struct option_cache *)0;
+       struct iaddr myfrom;
 
        option_state_allocate (&options, MDL);
        memset (&outgoing, 0, sizeof outgoing);
@@ -967,6 +1000,43 @@ void nak_lease (packet, cip)
        save_option (&dhcp_universe, options, oc);
        option_cache_dereference (&oc, MDL);
                     
+       i = DHO_DHCP_SERVER_IDENTIFIER;
+       if (!(oc = lookup_option (&dhcp_universe, options, i))) {
+             use_primary:
+               oc = (struct option_cache *)0;
+               if (option_cache_allocate (&oc, MDL)) {
+                       if (make_const_data
+                           (&oc -> expression,
+                            ((unsigned char *)
+                             &packet -> interface -> primary_address),
+                            sizeof packet -> interface -> primary_address,
+                            0, 0)) {
+                               oc -> option =
+                                       dhcp_universe.options [i];
+                               save_option (&dhcp_universe, options, oc);
+                       }
+                       option_cache_dereference (&oc, MDL);
+               }
+               myfrom.len = sizeof packet -> interface -> primary_address;
+               memcpy (myfrom.iabuf,
+                       &packet -> interface -> primary_address, myfrom.len);
+       } else {
+               memset (&data, 0, sizeof data);
+               if (evaluate_option_cache (&data, packet, (struct lease *)0,
+                                          packet -> options, options,
+                                          &global_scope, oc, MDL)) {
+                       if (!data.len ||
+                           data.len > sizeof myfrom.iabuf) {
+                               data_string_forget (&data, MDL);
+                               goto use_primary;
+                       }
+                       memcpy (myfrom.iabuf, data.data, data.len);
+                       myfrom.len = data.len;
+                       data_string_forget (&data, MDL);
+               } else
+                       goto use_primary;
+       }
+
        /* Do not use the client's requested parameter list. */
        delete_option (&dhcp_universe, packet -> options,
                       DHO_DHCP_PARAMETER_REQUEST_LIST);
@@ -1022,7 +1092,7 @@ void nak_lease (packet, cip)
 #endif
        memset (to.sin_zero, 0, sizeof to.sin_zero);
 
-       from = packet -> interface -> primary_address;
+       memcpy (&from, myfrom.iabuf, sizeof from);
 
        /* Make sure that the packet is at least as big as a BOOTP packet. */
        if (outgoing.packet_length < BOOTP_MIN_LEN)
@@ -1063,7 +1133,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
        char *msg;
        int ms_nulltp;
 {
-       struct lease lt;
+       struct lease *lt;
        struct lease_state *state;
        TIME lease_time;
        TIME offered_lease_time;
@@ -1074,6 +1144,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
        struct option_cache *oc;
        struct expression *expr;
        int status;
+       isc_result_t result;
 
        unsigned i, j;
        int s1, s2;
@@ -1089,7 +1160,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
        if (!state)
                log_fatal ("unable to allocate lease state!");
        state -> got_requested_address = packet -> got_requested_address;
-       state -> shared_network = packet -> interface -> shared_network;
+       shared_network_reference (&state -> shared_network,
+                                 packet -> interface -> shared_network, MDL);
 
        /* See if we got a server identifier option. */
        if (lookup_option (&dhcp_universe,
@@ -1208,21 +1280,27 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                                           oc, MDL)) {
                struct lease *seek;
                if (lease -> uid_len) {
+                       struct lease *s;
                        do {
-                               seek = find_lease_by_uid (lease -> uid,
-                                                         lease -> uid_len);
+                               seek = (struct lease *)0;
+                               find_lease_by_uid (&seek, lease -> uid,
+                                                  lease -> uid_len, MDL);
+
                                /* Don't release expired leases, and don't
                                   release the lease we're going to assign. */
-                               while (seek) {
-                                       if (seek != lease &&
-                                           seek -> ends > cur_time)
+                               s = seek;
+                               while (s) {
+                                       if (s != lease &&
+                                           s -> ends > cur_time)
                                                break;
-                                       seek = seek -> n_uid;
+                                       s = s -> n_uid;
                                }
-                               if (seek) {
+                               if (s) {
                                        release_lease (seek, packet);
                                }
-                       } while (seek);
+                               if (seek)
+                                       lease_dereference (&seek, MDL);
+                       } while (s);
                }
                if (!lease -> uid_len ||
                    (lease -> host &&
@@ -1234,20 +1312,25 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                                                     state -> options,
                                                     &lease -> scope,
                                                     oc, MDL))) {
+                       struct lease *s;
                        do {
-                               seek = (find_lease_by_hw_addr
-                                       (lease -> hardware_addr.hbuf,
-                                        lease -> hardware_addr.hlen));
-                               while (seek) {
-                                       if (seek != lease &&
-                                           seek -> ends > cur_time)
+                               seek = (struct lease *)0;
+                               find_lease_by_hw_addr
+                                       (&seek, lease -> hardware_addr.hbuf,
+                                        lease -> hardware_addr.hlen, MDL);
+                               s = seek;
+                               while (s) {
+                                       if (s != lease &&
+                                           s -> ends > cur_time)
                                                break;
-                                       seek = seek -> n_hw;
+                                       s = s -> n_hw;
                                }
-                               if (seek) {
-                                       release_lease (seek, packet);
+                               if (s) {
+                                       release_lease (s, packet);
                                }
-                       } while (seek);
+                               if (seek)
+                                       lease_dereference (&s, MDL);
+                       } while (s);
                }
        }
        
@@ -1287,18 +1370,24 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                    evaluate_option_cache (&d1, packet, lease,
                                           packet -> options, state -> options,
                                           &lease -> scope, oc, MDL)) {
-                       hp = find_hosts_by_uid (d1.data, d1.len);
+                       struct host_decl *h;
+                       hp = (struct host_decl *)0;
+                       find_hosts_by_uid (&hp, d1.data, d1.len, MDL);
                        data_string_forget (&d1, MDL);
                        if (!hp)
-                               hp = find_hosts_by_haddr
-                                       (packet -> raw -> htype,
-                                        packet -> raw -> chaddr,
-                                        packet -> raw -> hlen);
-                       for (; hp; hp = hp -> n_ipaddr) {
-                               if (!hp -> fixed_addr)
+                               find_hosts_by_haddr (&hp,
+                                                    packet -> raw -> htype,
+                                                    packet -> raw -> chaddr,
+                                                    packet -> raw -> hlen,
+                                                    MDL);
+                       for (h = hp; h; h = h -> n_ipaddr) {
+                               if (!h -> fixed_addr)
                                        break;
                        }
-                       lease -> host = hp;
+                       if (h)
+                               host_reference (&lease -> host, hp, MDL);
+                       if (hp)
+                               host_dereference (&hp, MDL);
                } else
                        lease -> host = (struct host_decl *)0;
        }
@@ -1408,14 +1497,22 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
        /* At this point, we have a lease that we can offer the client.
           Now we construct a lease structure that contains what we want,
           and call supersede_lease to do the right thing with it. */
-       memset (&lt, 0, sizeof lt);
-
+       lt = (struct lease *)0;
+       result = lease_allocate (&lt, MDL);
+       if (result != ISC_R_SUCCESS) {
+               log_info ("%s: can't allocate temporary lease structure: %s",
+                         msg, isc_result_totext (result));
+               free_lease_state (state, MDL);
+               static_lease_dereference (lease, MDL);
+               return;
+       }
+               
        /* Use the ip address of the lease that we finally found in
           the database. */
-       lt.ip_addr = lease -> ip_addr;
+       lt -> ip_addr = lease -> ip_addr;
 
        /* Start now. */
-       lt.starts = cur_time;
+       lt -> starts = cur_time;
 
        /* Figure out how long a lease to assign.    If this is a
           dynamic BOOTP lease, its duration must be infinite. */
@@ -1497,7 +1594,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
 #if defined (FAILOVER_PROTOCOL)
                /* Okay, we know the lease duration.   Now check the
                   failover state, if any. */
-               if (lease -> pool -> failover_peer) {
+               if (lease -> pool && lease -> pool -> failover_peer) {
                        dhcp_failover_state_t *peer =
                            lease -> pool -> failover_peer;
 
@@ -1512,7 +1609,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                                   to update tstp, there's already an update
                                   queued.   May want to revisit this.  */
                                if (cur_time + lease_time > lease -> tstp)
-                                       lt.tstp = cur_time + lease_time;
+                                       lt -> tstp = cur_time + lease_time;
 
                                /* Now choose a lease time that is either
                                   MCLT, for a lease that's never before been
@@ -1528,7 +1625,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                                        lease_time = (lease -> tsfp  - cur_time
                                                      + peer -> mclt);
                        }
-                       lt.cltt = cur_time;
+                       lt -> cltt = cur_time;
                }
 #endif /* FAILOVER_PROTOCOL */
 
@@ -1539,9 +1636,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                else
                        state -> offered_expiry = cur_time + lease_time;
                if (when)
-                       lt.ends = when;
+                       lt -> ends = when;
                else
-                       lt.ends = state -> offered_expiry;
+                       lt -> ends = state -> offered_expiry;
        } else {
                lease_time = MAX_TIME - cur_time;
 
@@ -1570,11 +1667,11 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                        }
                }
 
-               lt.ends = state -> offered_expiry = cur_time + lease_time;
-               lt.flags = BOOTP_LEASE;
+               lt -> ends = state -> offered_expiry = cur_time + lease_time;
+               lt -> flags = BOOTP_LEASE;
        }
 
-       lt.timestamp = cur_time;
+       lt -> timestamp = cur_time;
 
        /* Record the uid, if given... */
        oc = lookup_option (&dhcp_universe, packet -> options,
@@ -1583,28 +1680,32 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
            evaluate_option_cache (&d1, packet, lease,
                                   packet -> options, state -> options,
                                   &lease -> scope, oc, MDL)) {
-               if (d1.len <= sizeof lt.uid_buf) {
-                       memcpy (lt.uid_buf, d1.data, d1.len);
-                       lt.uid = lt.uid_buf;
-                       lt.uid_max = sizeof lt.uid_buf;
-                       lt.uid_len = d1.len;
+               if (d1.len <= sizeof lt -> uid_buf) {
+                       memcpy (lt -> uid_buf, d1.data, d1.len);
+                       lt -> uid = lt -> uid_buf;
+                       lt -> uid_max = sizeof lt -> uid_buf;
+                       lt -> uid_len = d1.len;
                } else {
                        unsigned char *tuid;
-                       lt.uid_max = d1.len;
-                       lt.uid_len = d1.len;
-                       tuid = (unsigned char *)dmalloc (lt.uid_max, MDL);
+                       lt -> uid_max = d1.len;
+                       lt -> uid_len = d1.len;
+                       tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL);
                        /* XXX inelegant */
                        if (!tuid)
                                log_fatal ("no memory for large uid.");
-                       memcpy (tuid, d1.data, lt.uid_len);
-                       lt.uid = tuid;
+                       memcpy (tuid, d1.data, lt -> uid_len);
+                       lt -> uid = tuid;
                }
                data_string_forget (&d1, MDL);
        }
 
-       lt.host = lease -> host;
-       lt.subnet = lease -> subnet;
-       lt.billing_class = lease -> billing_class;
+       if (lease -> host)
+               host_reference (&lt -> host, lease -> host, MDL);
+       if (lease -> subnet)
+               subnet_reference (&lt -> subnet, lease -> subnet, MDL);
+       if (lease -> billing_class)
+               class_reference (&lt -> billing_class,
+                                lease -> billing_class, MDL);
 
        /* Set a flag if this client is a broken client that NUL
           terminates string options and expects us to do likewise. */
@@ -1625,7 +1726,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
        }
 
        /* Save any bindings. */
-       lt.scope.bindings = lease -> scope.bindings;
+       lt -> scope.bindings = lease -> scope.bindings;
        lease -> scope.bindings = (struct binding *)0;
 
        /* Don't call supersede_lease on a mocked-up lease. */
@@ -1639,9 +1740,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                        sizeof packet -> raw -> chaddr); /* XXX */
        } else {
                /* Record the hardware address, if given... */
-               lt.hardware_addr.hlen = packet -> raw -> hlen + 1;
-               lt.hardware_addr.hbuf [0] = packet -> raw -> htype;
-               memcpy (&lt.hardware_addr.hbuf [1], packet -> raw -> chaddr,
+               lt -> hardware_addr.hlen = packet -> raw -> hlen + 1;
+               lt -> hardware_addr.hbuf [0] = packet -> raw -> htype;
+               memcpy (&lt -> hardware_addr.hbuf [1], packet -> raw -> chaddr,
                        sizeof packet -> raw -> chaddr);
 
                /* Install the new information about this lease in the
@@ -1649,12 +1750,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                   and we can't write the lease, don't ACK it (or BOOTREPLY
                   it) either. */
 
-               if (!(supersede_lease (lease, &lt, !offer || offer == DHCPACK,
+               if (!(supersede_lease (lease, lt, !offer || offer == DHCPACK,
                                       offer == DHCPACK)
                      || (offer && offer != DHCPACK))) {
                        log_info ("%s: database update failed", msg);
                        free_lease_state (state, MDL);
                        static_lease_dereference (lease, MDL);
+                       lease_dereference (&lt, MDL);
                        return;
                } else {
                        /* If this is a DHCPOFFER transaction, supersede_lease
@@ -1668,9 +1770,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
                        if (offer == DHCPOFFER && lease -> pool &&
                            lease -> pool -> next_expiry == lease)
                                add_timeout (lease -> ends, pool_timer,
-                                            lease -> pool);
+                                            lease -> pool,
+                                            (tvref_t)omapi_object_reference,
+                                            (tvunref_t)
+                                            omapi_object_dereference);
                }
        }
+       lease_dereference (&lt, MDL);
 
        /* Remember the interface on which the packet arrived. */
        state -> ip = packet -> interface;
@@ -2001,11 +2107,10 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
            evaluate_option_cache (&d1, packet, lease,
                                   packet -> options, state -> options,
                                   &lease -> scope, oc, MDL)) {
-               const struct universe *u;
-               
-               u = ((const struct universe *)
-                    hash_lookup (universe_hash, d1.data, d1.len));
-               if (!u) {
+               struct universe *u = (struct universe *)0;
+
+               if (!universe_hash_lookup (&u, universe_hash,
+                                          d1.data, d1.len, MDL)) {
                        log_error ("unknown option space %s.", d1.data);
                        return;
                }
@@ -2053,7 +2158,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp)
            cur_time - lease -> timestamp > 60) {
                lease -> timestamp = cur_time;
                icmp_echorequest (&lease -> ip_addr);
-               add_timeout (cur_time + 1, lease_ping_timeout, lease);
+               add_timeout (cur_time + 1, lease_ping_timeout, lease,
+                            (tvref_t)lease_reference,
+                            (tvunref_t)lease_dereference);
                ++outstanding_pings;
        } else {
                lease -> timestamp = cur_time;
@@ -2273,16 +2380,19 @@ void dhcp_reply (lease)
        lease -> state = (struct lease_state *)0;
 }
 
-struct lease *find_lease (packet, share, ours)
-       struct packet *packet;
-       struct shared_network *share;
-       int *ours;
+int find_lease (struct lease **lp,
+               struct packet *packet, struct shared_network *share, int *ours,
+               const char *file, int line)
 {
-       struct lease *uid_lease, *ip_lease, *hw_lease;
+       struct lease *uid_lease = (struct lease *)0;
+       struct lease *ip_lease = (struct lease *)0;
+       struct lease *hw_lease = (struct lease *)0;
        struct lease *lease = (struct lease *)0;
        struct iaddr cip;
-       struct host_decl *hp, *host = (struct host_decl *)0;
-       struct lease *fixed_lease, *next;
+       struct host_decl *hp = (struct host_decl *)0;
+       struct host_decl *host = (struct host_decl *)0;
+       struct lease *fixed_lease = (struct lease *)0;
+       struct lease *next;
        struct option_cache *oc;
        struct data_string d1;
        int have_client_identifier = 0;
@@ -2323,14 +2433,12 @@ struct lease *find_lease (packet, share, ours)
 
                /* First, try to find a fixed host entry for the specified
                   client identifier... */
-               hp = find_hosts_by_uid (client_identifier.data,
-                                       client_identifier.len);
-               if (hp) {
+               if (find_hosts_by_uid (&hp, client_identifier.data,
+                                      client_identifier.len, MDL)) {
                        /* Remember if we know of this client. */
                        packet -> known = 1;
-                       fixed_lease = mockup_lease (packet, share, hp);
-               } else
-                       fixed_lease = (struct lease *)0;
+                       mockup_lease (&fixed_lease, packet, share, hp);
+               }
 
 #if defined (DEBUG_FIND_LEASE)
                if (fixed_lease) {
@@ -2338,27 +2446,28 @@ struct lease *find_lease (packet, share, ours)
                              piaddr (fixed_lease -> ip_addr));
                }
 #endif
-               if (!fixed_lease)
-                       host = hp;      /* Save the host if we found one. */
+               if (!fixed_lease)       /* Save the host if we found one. */
+                       host_reference (&host, hp, MDL);
+               if (hp)
+                       host_dereference (&hp, MDL);
 
-               uid_lease = find_lease_by_uid (client_identifier.data,
-                                              client_identifier.len);
-       } else {
-               uid_lease = (struct lease *)0;
-               fixed_lease = (struct lease *)0;
+               find_lease_by_uid (&uid_lease, client_identifier.data,
+                                  client_identifier.len, MDL);
        }
 
        /* If we didn't find a fixed lease using the uid, try doing
           it with the hardware address... */
        if (!fixed_lease && !host) {
-               hp = find_hosts_by_haddr (packet -> raw -> htype,
-                                         packet -> raw -> chaddr,
-                                         packet -> raw -> hlen);
-               if (hp) {
+               if (find_hosts_by_haddr (&hp, packet -> raw -> htype,
+                                        packet -> raw -> chaddr,
+                                        packet -> raw -> hlen, MDL)) {
                        /* Remember if we know of this client. */
                        packet -> known = 1;
-                       host = hp; /* Save it for later. */
-                       fixed_lease = mockup_lease (packet, share, hp);
+                       if (host)
+                               host_dereference (&host, MDL);
+                       host_reference (&host, hp, MDL);
+                       host_dereference (&hp, MDL);
+                       mockup_lease (&fixed_lease, packet, share, host);
 #if defined (DEBUG_FIND_LEASE)
                        if (fixed_lease) {
                                log_info ("Found host for link address: %s.",
@@ -2391,7 +2500,7 @@ struct lease *find_lease (packet, share, ours)
           can't do this until we get here because we depend on
           packet -> known, which may be set by either the uid host
           lookup or the haddr host lookup. */
-       for (; uid_lease; uid_lease = next) {
+       while (uid_lease) {
 #if defined (DEBUG_FIND_LEASE)
                log_info ("trying next lease matching client id: %s",
                          piaddr (uid_lease -> ip_addr));
@@ -2402,6 +2511,8 @@ struct lease *find_lease (packet, share, ours)
                                  piaddr (uid_lease -> ip_addr));
 #endif
                        next = uid_lease -> n_uid;
+                       lease_dereference (&uid_lease, MDL);
+                       lease_reference (&uid_lease, next, MDL);
                        continue;
                }
                if ((uid_lease -> pool -> prohibit_list &&
@@ -2415,6 +2526,8 @@ struct lease *find_lease (packet, share, ours)
                        next = uid_lease -> n_uid;
                        if (!packet -> raw -> ciaddr.s_addr)
                                release_lease (uid_lease, packet);
+                       lease_dereference (&uid_lease, MDL);
+                       lease_reference (&uid_lease, next, MDL);
                        continue;
                }
                break;
@@ -2431,8 +2544,8 @@ struct lease *find_lease (packet, share, ours)
        h.hlen = packet -> raw -> hlen + 1;
        h.hbuf [0] = packet -> raw -> htype;
        memcpy (&h.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen);
-       hw_lease = find_lease_by_hw_addr (h.hbuf, h.hlen);
-       for (; hw_lease; hw_lease = next) {
+       find_lease_by_hw_addr (&hw_lease, h.hbuf, h.hlen, MDL);
+       while (hw_lease) {
 #if defined (DEBUG_FIND_LEASE)
                log_info ("trying next lease matching hw addr: %s",
                          piaddr (hw_lease -> ip_addr));
@@ -2448,6 +2561,8 @@ struct lease *find_lease (packet, share, ours)
                                  piaddr (hw_lease -> ip_addr));
 #endif
                        next = hw_lease -> n_hw;
+                       lease_dereference (&hw_lease, MDL);
+                       lease_reference (&hw_lease, next, MDL);
                        continue;
                }
                if (hw_lease -> subnet -> shared_network != share) {
@@ -2456,6 +2571,8 @@ struct lease *find_lease (packet, share, ours)
                                  piaddr (hw_lease -> ip_addr));
 #endif
                        next = hw_lease -> n_hw;
+                       lease_dereference (&hw_lease, MDL);
+                       lease_reference (&hw_lease, next, MDL);
                        continue;
                }
                if ((hw_lease -> pool -> prohibit_list &&
@@ -2469,6 +2586,8 @@ struct lease *find_lease (packet, share, ours)
                        next = hw_lease -> n_hw;
                        if (!packet -> raw -> ciaddr.s_addr)
                                release_lease (hw_lease, packet);
+                       lease_dereference (&hw_lease, MDL);
+                       lease_reference (&hw_lease, next, MDL);
                        continue;
                }
                break;
@@ -2482,9 +2601,7 @@ struct lease *find_lease (packet, share, ours)
        /* Try to find a lease that's been allocated to the client's
           IP address. */
        if (cip.len)
-               ip_lease = find_lease_by_ip_addr (cip);
-       else
-               ip_lease = (struct lease *)0;
+               find_lease_by_ip_addr (&ip_lease, cip, MDL);
 
 #if defined (DEBUG_FIND_LEASE)
        if (ip_lease)
@@ -2512,7 +2629,7 @@ struct lease *find_lease (packet, share, ours)
                log_info ("...but it was on the wrong shared network.");
 #endif
                strcpy (dhcp_message, "requested address on bad subnet");
-               ip_lease = (struct lease *)0;
+               lease_dereference (&ip_lease, MDL);
        }
 
        /* Toss ip_lease if it hasn't yet expired and doesn't belong to the
@@ -2534,7 +2651,7 @@ struct lease *find_lease (packet, share, ours)
                if (ip_lease)
                        log_info ("rejecting lease for requested address.");
 #endif
-               ip_lease = (struct lease *)0;
+               lease_dereference (&ip_lease, MDL);
        }
 
        /* If for some reason the client has more than one lease
@@ -2568,7 +2685,8 @@ struct lease *find_lease (packet, share, ours)
                                    packet -> packet_type == DHCPREQUEST)
                                        dissociate_lease (uid_lease);
                            }
-                           uid_lease = ip_lease;
+                           lease_dereference (&uid_lease, MDL);
+                           lease_reference (&uid_lease, ip_lease, MDL);
                        }
                }
 
@@ -2576,7 +2694,7 @@ struct lease *find_lease (packet, share, ours)
                   that there are both a dynamic lease and a fixed-address
                   declaration for the same IP address. */
                if (packet -> packet_type == DHCPREQUEST && fixed_lease) {
-                       fixed_lease = (struct lease *)0;
+                       lease_dereference (&fixed_lease, MDL);
                      db_conflict:
                        log_error ("Dynamic and static leases present for %s.",
                                   piaddr (cip));
@@ -2591,7 +2709,7 @@ struct lease *find_lease (packet, share, ours)
                                   ip_lease -> subnet -> shared_network -> name
                                  );
                        if (fixed_lease)
-                               ip_lease = (struct lease *)0;
+                               lease_dereference (&ip_lease, MDL);
                        strcpy (dhcp_message,
                                "database conflict - call for help!");
                }
@@ -2610,24 +2728,24 @@ struct lease *find_lease (packet, share, ours)
              !permitted (packet, ip_lease -> pool -> permit_list)))) {
                if (!packet -> raw -> ciaddr.s_addr)
                        release_lease (ip_lease, packet);
-               ip_lease = (struct lease *)0;
+               lease_dereference (&ip_lease, MDL);
        }
 
        /* Toss extra pointers to the same lease... */
-       if (hw_lease == uid_lease) {
+       if (hw_lease && hw_lease == uid_lease) {
 #if defined (DEBUG_FIND_LEASE)
                log_info ("hardware lease and uid lease are identical.");
 #endif
-               hw_lease = (struct lease *)0;
+               lease_dereference (&hw_lease, MDL);
        }
-       if (ip_lease == hw_lease) {
-               hw_lease = (struct lease *)0;
+       if (ip_lease && ip_lease == hw_lease) {
+               lease_dereference (&hw_lease, MDL);
 #if defined (DEBUG_FIND_LEASE)
                log_info ("hardware lease and ip lease are identical.");
 #endif
        }
-       if (ip_lease == uid_lease) {
-               uid_lease = (struct lease *)0;
+       if (ip_lease && ip_lease == uid_lease) {
+               lease_dereference (&uid_lease, MDL);
 #if defined (DEBUG_FIND_LEASE)
                log_info ("uid lease and ip lease are identical.");
 #endif
@@ -2654,7 +2772,8 @@ struct lease *find_lease (packet, share, ours)
        /* At this point, if fixed_lease is nonzero, we can assign it to
           this client. */
        if (fixed_lease) {
-               lease = fixed_lease;
+               lease_reference (&lease, fixed_lease, MDL);
+               lease_dereference (&fixed_lease, MDL);
 #if defined (DEBUG_FIND_LEASE)
                log_info ("choosing fixed address.");
 #endif
@@ -2673,9 +2792,11 @@ struct lease *find_lease (packet, share, ours)
 #if defined (DEBUG_FIND_LEASE)
                        log_info ("choosing lease on requested address.");
 #endif
-                       lease = ip_lease;
-                       lease -> host = (struct host_decl *)0;
+                       lease_reference (&lease, ip_lease, MDL);
+                       if (lease -> host)
+                               host_dereference (&lease -> host, MDL);
                }
+               lease_dereference (&ip_lease, MDL);
        }
 
        /* If we got a lease that matched the client identifier, we may want
@@ -2689,13 +2810,16 @@ struct lease *find_lease (packet, share, ours)
 #if defined (DEBUG_FIND_LEASE)
                        log_info ("not choosing uid lease.");
 #endif
+                       lease_dereference (&uid_lease, MDL);
                } else {
-                       lease = uid_lease;
-                       lease -> host = (struct host_decl *)0;
+                       lease_reference (&lease, uid_lease, MDL);
+                       if (lease -> host)
+                               host_dereference (&lease -> host, MDL);
 #if defined (DEBUG_FIND_LEASE)
                        log_info ("choosing uid lease.");
 #endif
                }
+               lease_dereference (&uid_lease, MDL);
        }
 
        /* The lease that matched the hardware address is treated likewise. */
@@ -2704,16 +2828,19 @@ struct lease *find_lease (packet, share, ours)
                        if (!packet -> raw -> ciaddr.s_addr &&
                            packet -> packet_type == DHCPREQUEST)
                                dissociate_lease (hw_lease);
+                       lease_dereference (&hw_lease, MDL);
 #if defined (DEBUG_FIND_LEASE)
                        log_info ("not choosing hardware lease.");
 #endif
                } else {
-                       lease = hw_lease;
-                       lease -> host = (struct host_decl *)0;
+                       lease_reference (&lease, hw_lease, MDL);
+                       if (lease -> host)
+                               host_dereference (&lease -> host, MDL);
 #if defined (DEBUG_FIND_LEASE)
                        log_info ("choosing hardware lease.");
 #endif
                }
+               lease_dereference (&hw_lease, MDL);
        }
 
        /* If we found a host_decl but no matching address, try to
@@ -2723,7 +2850,7 @@ struct lease *find_lease (packet, share, ours)
        if (lease && host && !lease -> host) {
                for (; host; host = host -> n_ipaddr) {
                        if (!host -> fixed_addr) {
-                               lease -> host = host;
+                               host_reference (&lease -> host, host, MDL);
                                break;
                        }
                }
@@ -2745,54 +2872,76 @@ struct lease *find_lease (packet, share, ours)
           to go back through the allocation process. */
                if (ours)
                        *ours = 1;
-               lease = (struct lease *)0;
+               lease_dereference (&lease, MDL);
        }
 
       out:
        if (have_client_identifier)
                data_string_forget (&client_identifier, MDL);
 
+       if (fixed_lease)
+               lease_dereference (&fixed_lease, MDL);
+       if (hw_lease)
+               lease_dereference (&hw_lease, MDL);
+       if (uid_lease)
+               lease_dereference (&uid_lease, MDL);
+       if (ip_lease)
+               lease_dereference (&ip_lease, MDL);
+       if (host)
+               host_dereference (&host, MDL);
+
+       if (lease) {
 #if defined (DEBUG_FIND_LEASE)
-       if (lease)
                log_info ("Returning lease: %s.",
                      piaddr (lease -> ip_addr));
-       else
-               log_info ("Not returning a lease.");
 #endif
-
-       return lease;
+               lease_reference (lp, lease, file, line);
+               lease_dereference (&lease, MDL);
+               return 1;
+       }
+#if defined (DEBUG_FIND_LEASE)
+       log_info ("Not returning a lease.");
+#endif
+       return 0;
 }
 
 /* Search the provided host_decl structure list for an address that's on
    the specified shared network.  If one is found, mock up and return a
    lease structure for it; otherwise return the null pointer. */
 
-struct lease *mockup_lease (packet, share, hp)
-       struct packet *packet;
-       struct shared_network *share;
-       struct host_decl *hp;
+int mockup_lease (struct lease **lp, struct packet *packet,
+                 struct shared_network *share, struct host_decl *hp)
 {
-       static struct lease mock;
+       struct lease *lease = (struct lease *)0;
        const unsigned char **s;
+       isc_result_t status;
        
-       mock.subnet = find_host_for_network (&hp, &mock.ip_addr, share);
-       if (!mock.subnet)
-               return (struct lease *)0;
-       mock.next = mock.prev = (struct lease *)0;
-       mock.host = hp;
-       if (hp -> client_identifier.len > sizeof mock.uid_buf)
-               mock.uid = dmalloc (hp -> client_identifier.len, MDL);
+       status = lease_allocate (&lease, MDL);
+       if (status != ISC_R_SUCCESS)
+               return 0;
+       if (!find_host_for_network (&lease -> subnet,
+                                   &hp, &lease -> ip_addr, share)) {
+               lease_dereference (&lease, MDL);
+               return 0;
+       }
+       host_reference (&lease -> host, hp, MDL);
+       if (hp -> client_identifier.len > sizeof lease -> uid_buf)
+               lease -> uid = dmalloc (hp -> client_identifier.len, MDL);
        else
-               mock.uid = mock.uid_buf;
-       if (!mock.uid)
-               return (struct lease *)0;
-       memcpy (mock.uid, hp -> client_identifier.data,
+               lease -> uid = lease -> uid_buf;
+       if (!lease -> uid) {
+               lease_dereference (&lease, MDL);
+               return 0;
+       }
+       memcpy (lease -> uid, hp -> client_identifier.data,
                hp -> client_identifier.len);
-       mock.uid_len = hp -> client_identifier.len;
-       mock.hardware_addr = hp -> interface;
-       mock.starts = mock.timestamp = mock.ends = MIN_TIME;
-       mock.flags = STATIC_LEASE;
-       return &mock;
+       lease -> uid_len = hp -> client_identifier.len;
+       lease -> hardware_addr = hp -> interface;
+       lease -> starts = lease -> timestamp = lease -> ends = MIN_TIME;
+       lease -> flags = STATIC_LEASE;
+       lease_reference (lp, lease, MDL);
+       lease_dereference (&lease, MDL);
+       return 1;
 }
 
 /* Dereference all dynamically-allocated information that may be dangling
@@ -2831,23 +2980,20 @@ void static_lease_dereference (lease, file, line)
    lease.   If all of these possibilities fail to pan out, we don't return
    a lease at all. */
 
-struct lease *allocate_lease (packet, pool, ok, peer_has_leases)
-       struct packet *packet;
-       struct pool *pool;
-       int ok;
-       int *peer_has_leases;
+int allocate_lease (struct lease **lp, struct packet *packet,
+                   struct pool *pool, int *peer_has_leases)
 {
-       struct lease *lease, *lp;
+       struct lease *lease = (struct lease *)0;
        struct permit *permit;
 
        if (!pool)
-               return (struct lease *)0;
+               return 0;
 
        /* If we aren't elegible to try this pool, try a subsequent one. */
        if ((pool -> prohibit_list &&
             permitted (packet, pool -> prohibit_list)) ||
            (pool -> permit_list && !permitted (packet, pool -> permit_list)))
-               return allocate_lease (packet, pool -> next, ok,
+               return allocate_lease (lp, packet, pool -> next,
                                       peer_has_leases);
 
        lease = pool -> last_lease;
@@ -2880,8 +3026,8 @@ struct lease *allocate_lease (packet, pool, ok, peer_has_leases)
        /* If there are no leases in the pool that have
           expired, try the next one. */
        if (!lease || lease -> ends > cur_time)
-               return allocate_lease (packet,
-                                      pool -> next, ok, peer_has_leases);
+               return allocate_lease (lp, packet,
+                                      pool -> next, peer_has_leases);
 
        /* If we find an abandoned lease, and no other lease qualifies
           better, take it. */
@@ -2890,17 +3036,17 @@ struct lease *allocate_lease (packet, pool, ok, peer_has_leases)
        if ((lease -> flags & ABANDONED_LEASE)) {
                /* If we already have a non-abandoned lease that we didn't
                   love, but that's okay, don't reclaim the abandoned lease. */
-               if (ok)
-                       return allocate_lease (packet, pool -> next,
-                                              ok, peer_has_leases);
-               lp = allocate_lease (packet, pool -> next, 0, peer_has_leases);
-               if (!lp) {
+               if (*lp)
+                       return allocate_lease (lp, packet, pool -> next,
+                                              peer_has_leases);
+               if (!allocate_lease (lp, packet,
+                                    pool -> next, peer_has_leases)) {
                        log_error ("Reclaiming abandoned IP address %s.",
                              piaddr (lease -> ip_addr));
                        lease -> flags &= ~ABANDONED_LEASE;
-                       return lease;
+                       lease_reference (lp, lease, MDL);
                }
-               return lp;
+               return 1;
        }
 
        /* If there's a lease we could take, but it had previously been
@@ -2909,17 +3055,17 @@ struct lease *allocate_lease (packet, pool, ok, peer_has_leases)
        if (lease -> uid_len || lease -> hardware_addr.hlen) {
                /* If we're already in that boat, no need to consider
                   allocating this particular lease. */
-               if (ok)
-                       return allocate_lease (packet, pool -> next,
-                                              ok, peer_has_leases);
+               if (*lp)
+                       return allocate_lease (lp, packet, pool -> next,
+                                              peer_has_leases);
 
-               lp = allocate_lease (packet, pool -> next, 1, peer_has_leases);
-               if (lp)
-                       return lp;
-               return lease;
+               allocate_lease (lp, packet, pool -> next, peer_has_leases);
+               if (*lp)
+                       return 1;
        }
 
-       return lease;
+       lease_reference (lp, lease, MDL);
+       return 1;
 }
 
 /* Determine whether or not a permit exists on a particular permit list
@@ -2985,7 +3131,7 @@ int locate_network (packet)
 {
        struct iaddr ia;
        struct data_string data;
-       struct subnet *subnet;
+       struct subnet *subnet = (struct subnet *)0;
        struct option_cache *oc;
 
        /* See if there's a subnet selection option. */
@@ -2995,9 +3141,12 @@ int locate_network (packet)
        /* If there's no SSO and no giaddr, then use the shared_network
           from the interface, if there is one.   If not, fail. */
        if (!oc && !packet -> raw -> giaddr.s_addr) {
-               if ((packet -> shared_network =
-                    packet -> interface -> shared_network))
+               if (packet -> interface -> shared_network) {
+                       shared_network_reference
+                               (&packet -> shared_network,
+                                packet -> interface -> shared_network, MDL);
                        return 1;
+               }
                return 0;
        }
 
@@ -3009,11 +3158,9 @@ int locate_network (packet)
                                            packet -> options,
                                            (struct option_state *)0,
                                            &global_scope, oc, MDL)) {
-                       packet -> shared_network = (struct shared_network *)0;
                        return 0;
                }
                if (data.len != 4) {
-                       packet -> shared_network = (struct shared_network *)0;
                        return 0;
                }
                ia.len = 4;
@@ -3025,14 +3172,14 @@ int locate_network (packet)
        }
 
        /* If we know the subnet on which the IP address lives, use it. */
-       subnet = find_subnet (ia);
-       if (subnet) {
-               packet -> shared_network = subnet -> shared_network;
+       if (find_subnet (&subnet, ia, MDL)) {
+               shared_network_reference (&packet -> shared_network,
+                                         subnet -> shared_network, MDL);
+               subnet_dereference (&subnet, MDL);
                return 1;
        }
 
        /* Otherwise, fail. */
-       packet -> shared_network = (struct shared_network *)0;
        return 0;
 }
 
index acf1941a99a4ac10ed0bf15838f696f183c64299..f29ebcee3d6cccbb34d727cbeb432989e880ebf0 100644 (file)
@@ -15,7 +15,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
+ * 3. Neither the name of Internet Software Consortium nor the names
  *    of its contributors may be used to endorse or promote products derived
  *    from this software without specific prior written permission.
  *
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhcpd.c,v 1.90 2000/05/03 06:32:09 mellon Exp $ Copyright 1995-2000 The Internet Software Consortium.";
+"$Id: dhcpd.c,v 1.91 2000/05/16 23:03:43 mellon Exp $ Copyright 1995-2000 Internet Software Consortium.";
 #endif
 
   static char copyright[] =
-"Copyright 1995-2000 The Internet Software Consortium.";
+"Copyright 1995-2000 Internet Software Consortium.";
 static char arr [] = "All rights reserved.";
 static char message [] = "Internet Software Consortium DHCP Server";
 static char contrib [] = "\nPlease contribute if you find this software useful.";
@@ -60,7 +60,6 @@ static char url [] = "For info, please visit http://www.isc.org/dhcp-contrib.htm
 static void usage PROTO ((void));
 
 TIME cur_time;
-struct group root_group;
 struct binding_scope global_scope;
 
 struct iaddr server_identifier;
@@ -305,12 +304,15 @@ int main (argc, argv, envp)
        /* Set up the OMAPI wrappers for various server database internal
           objects. */
        dhcp_db_objects_setup ();
+       dhcp_common_objects_setup ();
 
        /* Set up the initial dhcp option universe. */
        initialize_common_option_spaces ();
        initialize_server_option_spaces ();
 
-       root_group.authoritative = 0;
+       if (!group_allocate (&root_group, MDL))
+               log_fatal ("Can't allocate root group!");
+       root_group -> authoritative = 0;
 
 #if defined (NSUPDATE)
        /* Set up the standard name service updater routine. */
@@ -322,7 +324,7 @@ int main (argc, argv, envp)
                log_fatal ("can't parse standard name service updater!");
 
        if (!(parse_executable_statements
-             (&root_group.statements, parse, &lose, context_any))) {
+             (&root_group -> statements, parse, &lose, context_any))) {
                end_parse (&parse);
                log_fatal ("can't parse standard name service updater!");
        }
@@ -344,7 +346,7 @@ int main (argc, argv, envp)
                                     (struct lease *)0,
                                     (struct option_state *)0,
                                     options, &global_scope,
-                                    &root_group,
+                                    root_group,
                                     (struct group *)0);
        memset (&db, 0, sizeof db);
        oc = lookup_option (&server_universe, options, SV_LEASE_FILE_NAME);
@@ -448,12 +450,16 @@ int main (argc, argv, envp)
        /* Don't need the options anymore. */
        option_state_dereference (&options, MDL);
        
+       group_write_hook = group_writer;
+
        /* Start up the database... */
        db_startup (lftest);
 
        if (lftest)
                exit (0);
 
+       dhcp_interface_setup_hook = dhcpd_interface_setup_hook;
+
        /* Discover all the network interfaces and initialize them. */
        discover_interfaces (DISCOVER_SERVER);
 
@@ -596,21 +602,21 @@ void lease_pinged (from, packet, length)
        if (!outstanding_pings)
                return;
 
-       lp = find_lease_by_ip_addr (from);
-
-       if (!lp) {
-               log_info ("unexpected ICMP Echo Reply from %s", piaddr (from));
+       lp = (struct lease *)0;
+       if (!find_lease_by_ip_addr (&lp, from, MDL)) {
+               log_debug ("unexpected ICMP Echo Reply from %s",
+                          piaddr (from));
                return;
        }
 
        if (!lp -> state) {
-               log_error ("ICMP Echo Reply for %s late or spurious.\n",
-                     piaddr (from));
-               return;
+               log_debug ("ICMP Echo Reply for %s late or spurious.\n",
+                          piaddr (from));
+               goto out;
        }
 
        if (lp -> ends > cur_time) {
-               log_error ("ICMP Echo reply while lease %s valid\n",
+               log_debug ("ICMP Echo reply while lease %s valid\n",
                           piaddr (from));
        }
 
@@ -623,6 +629,8 @@ void lease_pinged (from, packet, length)
        abandon_lease (lp, "pinged before offer");
        cancel_timeout (lease_ping_timeout, lp);
        --outstanding_pings;
+      out:
+       lease_dereference (&lp, MDL);
 }
 
 void lease_ping_timeout (vlp)
@@ -647,3 +655,59 @@ void lease_ping_timeout (vlp)
        dmalloc_dump_outstanding ();
 #endif
 }
+
+int dhcpd_interface_setup_hook (struct interface_info *ip, struct iaddr *ia)
+{
+       struct subnet *subnet;
+       struct shared_network *share;
+       isc_result_t status;
+
+       /* Special case for fallback network - not sure why this is
+          necessary. */
+       if (!ia) {
+               const char *fnn = "fallback-net";
+               char *s;
+               status = shared_network_allocate (&ip -> shared_network, MDL);
+               if (status != ISC_R_SUCCESS)
+                       log_fatal ("No memory for shared subnet: %s",
+                                  isc_result_totext (status));
+               ip -> shared_network -> name = dmalloc (strlen (fnn) + 1, MDL);
+               strcpy (ip -> shared_network -> name, fnn);
+               return 1;
+       }
+
+       /* If there's a registered subnet for this address,
+          connect it together... */
+       subnet = (struct subnet *)0;
+       if (find_subnet (&subnet, *ia, MDL)) {
+               /* If this interface has multiple aliases on the same
+                  subnet, ignore all but the first we encounter. */
+               if (!subnet -> interface) {
+                       subnet -> interface = ip;
+                       subnet -> interface_address = *ia;
+               } else if (subnet -> interface != ip) {
+                       log_error ("Multiple interfaces match the %s: %s %s", 
+                                  "same subnet",
+                                  subnet -> interface -> name, ip -> name);
+               }
+               share = subnet -> shared_network;
+               if (ip -> shared_network &&
+                   ip -> shared_network != share) {
+                       log_fatal ("Interface %s matches multiple shared %s",
+                                  ip -> name, "networks");
+               } else {
+                       if (!ip -> shared_network)
+                               shared_network_reference
+                                       (&ip -> shared_network, share, MDL);
+               }
+               
+               if (!share -> interface) {
+                       interface_reference (&share -> interface, ip, MDL);
+               } else if (share -> interface != ip) {
+                       log_error ("Multiple interfaces match the %s: %s %s", 
+                                  "same shared network",
+                                  share -> interface -> name, ip -> name);
+               }
+       }
+       return 1;
+}
index ddee88276b024c875cd379b43a525fe1f89a8d9f..6159b5d384b0748d5d30646645727ab7483edaf6 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: failover.c,v 1.13 2000/05/04 18:58:15 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: failover.c,v 1.14 2000/05/16 23:03:45 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -69,14 +69,21 @@ void dhcp_failover_startup ()
                        if (status != ISC_R_SUCCESS) {
                                add_timeout (cur_time + 90,
                                             dhcp_failover_listener_restart,
-                                            state);
+                                            state,
+                                            (tvref_t)omapi_object_reference,
+                                            (tvunref_t)
+                                            omapi_object_dereference);
                        }
                } else {
                        status = (dhcp_failover_link_initiate
                                  ((omapi_object_t *)state));
                        if (status != ISC_R_SUCCESS) {
                                add_timeout (cur_time + 90,
-                                            dhcp_failover_reconnect, state);
+                                            dhcp_failover_reconnect, state,
+                                            (tvref_t)
+                                            dhcp_failover_state_reference,
+                                            (tvunref_t)
+                                            dhcp_failover_state_dereference);
                        }
                }
                if (status != ISC_R_SUCCESS) {
@@ -101,28 +108,28 @@ isc_result_t enter_failover_peer (peer)
        dhcp_failover_state_t *dup = (dhcp_failover_state_t *)0;
        isc_result_t status;
 
-       status = find_failover_peer (&dup, peer -> name);
+       status = find_failover_peer (&dup, peer -> name, MDL);
        if (status == ISC_R_NOTFOUND) {
                if (failover_states) {
-                       omapi_object_reference
-                               ((omapi_object_t **)&peer -> next,
-                                (omapi_object_t *)failover_states, MDL);
-                       omapi_object_dereference
-                               ((omapi_object_t **)&failover_states, MDL);
+                       dhcp_failover_state_reference (&peer -> next,
+                                                     failover_states, MDL);
+                       dhcp_failover_state_dereference (&failover_states,
+                                                        MDL);
                }
-               omapi_object_reference ((omapi_object_t **)&failover_states,
-                                       (omapi_object_t *)peer, MDL);
+               dhcp_failover_state_reference (&failover_states, peer, MDL);
                return ISC_R_SUCCESS;
        }
+       dhcp_failover_state_dereference (&dup, MDL);
        if (status == ISC_R_SUCCESS)
                return ISC_R_EXISTS;
-
        return status;
 }
 
-isc_result_t find_failover_peer (peer, name)
+isc_result_t find_failover_peer (peer, name, file, line)
        dhcp_failover_state_t **peer;
        const char *name;
+       const char *file;
+       int line;
 {
        dhcp_failover_state_t *p;
 
@@ -130,8 +137,7 @@ isc_result_t find_failover_peer (peer, name)
                if (!strcmp (name, p -> name))
                        break;
        if (p)
-               return omapi_object_reference ((omapi_object_t **)peer,
-                                              (omapi_object_t *)p, MDL);
+               return dhcp_failover_state_reference (peer, p, file, line);
        return ISC_R_NOTFOUND;
 }
 
@@ -174,23 +180,20 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h)
                return ISC_R_INVALIDARG;
        state = (dhcp_failover_state_t *)o;
 
-       obj = (dhcp_failover_link_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       obj -> type = dhcp_type_failover_link;
+       obj = (dhcp_failover_link_t *)0;
+       status = dhcp_failover_link_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
        option_cache_reference (&obj -> peer_address, state -> address, MDL);
        obj -> peer_port = state -> port;
-       omapi_object_reference ((omapi_object_t **)&obj -> state_object,
-                               (omapi_object_t *)state, MDL);
+       dhcp_failover_state_reference (&obj -> state_object, state, MDL);
 
        memset (&ds, 0, sizeof ds);
        if (!evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0,
                                    (struct option_state *)0,
                                    (struct option_state *)0,
                                    &global_scope, obj -> peer_address, MDL)) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               dhcp_failover_link_dereference (&obj, MDL);
                return ISC_R_UNEXPECTED;
        }
 
@@ -198,7 +201,7 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h)
           IPv4 addresses. */
        status = omapi_addr_list_new (&addrs, ds.len / 4, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               dhcp_failover_link_dereference (&obj, MDL);
                return status;
        }
 
@@ -227,8 +230,7 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h)
        } else {
                if (ds.len != sizeof (struct in_addr)) {
                        data_string_forget (&ds, MDL);
-                       omapi_object_dereference ((omapi_object_t **)&obj,
-                                                 MDL);
+                       dhcp_failover_link_dereference (&obj, MDL);
                        omapi_addr_list_dereference (&addrs, MDL);
                        return ISC_R_INVALIDARG;
                }
@@ -246,14 +248,8 @@ isc_result_t dhcp_failover_link_initiate (omapi_object_t *h)
                                     addrs, &local_addr);
        omapi_addr_list_dereference (&addrs, MDL);
 
-       /* If we didn't succeed in starting to connect, fail. */
-       if (status != ISC_R_SUCCESS) {
-             loselose:
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-               return status;
-       }
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-       return ISC_R_SUCCESS;
+       dhcp_failover_link_dereference (&obj, MDL);
+       return status;
 }
 
 isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
@@ -284,8 +280,10 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
                if (link -> state_object &&
                    link -> state_object -> i_am == primary) {
                        add_timeout (cur_time + 90, dhcp_failover_reconnect,
-                                    link -> state_object);
-                       /* XXX this is a reference! */
+                                    link -> state_object,
+                                    (tvref_t)dhcp_failover_state_reference,
+                                    (tvunref_t)
+                                    dhcp_failover_state_dereference);
                }
                return ISC_R_SUCCESS;
        }
@@ -419,9 +417,8 @@ isc_result_t dhcp_failover_link_signal (omapi_object_t *h,
                    }
 
                    if (!link -> state_object)
-                           omapi_object_reference
-                                   ((omapi_object_t **)&link -> state_object,
-                                    (omapi_object_t *)state, MDL);
+                           dhcp_failover_state_reference
+                                   (&link -> state_object, state, MDL);
                    option_cache_reference
                            (&link -> peer_address, state -> address, MDL);
                }
@@ -732,8 +729,7 @@ isc_result_t dhcp_failover_link_destroy (omapi_object_t *h,
                link -> imsg = (failover_message_t *)0;
        }
        if (link -> state_object)
-               omapi_object_dereference
-                       ((omapi_object_t **)&link -> state_object, MDL);
+               dhcp_failover_state_dereference (&link -> state_object, MDL);
        return ISC_R_SUCCESS;
 }
 
@@ -826,12 +822,10 @@ isc_result_t dhcp_failover_listen (omapi_object_t *h)
 
        omapi_value_dereference (&value, MDL);
 
-       obj = (dhcp_failover_listener_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       obj -> type = dhcp_type_failover_listener;
+       obj = (dhcp_failover_listener_t *)0;
+       status = dhcp_failover_listener_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
        obj -> local_port = local_addr.port;
        
        status = omapi_listen_addr ((omapi_object_t *)obj, &local_addr, 1);
@@ -841,17 +835,16 @@ isc_result_t dhcp_failover_listen (omapi_object_t *h)
        status = omapi_object_reference (&h -> outer,
                                         (omapi_object_t *)obj, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               dhcp_failover_listener_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&obj -> inner, h, MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               dhcp_failover_listener_dereference (&obj, MDL);
                return status;
        }
 
-       status = omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-       return status;
+       return dhcp_failover_listener_dereference (&obj, MDL);
 }
 
 /* Signal handler for protocol listener - if we get a connect signal,
@@ -882,19 +875,17 @@ isc_result_t dhcp_failover_listener_signal (omapi_object_t *o,
        if (!c || c -> type != omapi_type_connection)
                return ISC_R_INVALIDARG;
 
-       obj = (dhcp_failover_link_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       obj -> type = dhcp_type_failover_link;
+       obj = (dhcp_failover_link_t *)0;
+       status = dhcp_failover_link_allocate (&obj, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
        obj -> peer_port = ntohs (c -> remote_addr.sin_port);
 
        status = omapi_object_reference (&obj -> outer,
                                         (omapi_object_t *)c, MDL);
        if (status != ISC_R_SUCCESS) {
              lose:
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               dhcp_failover_link_dereference (&obj, MDL);
                omapi_disconnect ((omapi_object_t *)c, 1);
                return status;
        }
@@ -904,8 +895,7 @@ isc_result_t dhcp_failover_listener_signal (omapi_object_t *o,
        if (status != ISC_R_SUCCESS)
                goto lose;
 
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-       return status;
+       return dhcp_failover_link_dereference (&obj, MDL);
 }
 
 isc_result_t dhcp_failover_listener_set_value (omapi_object_t *h,
@@ -985,31 +975,24 @@ isc_result_t dhcp_failover_register (omapi_object_t *h)
        if (status != ISC_R_SUCCESS)
                return status;
 
-       obj = (dhcp_failover_state_t *)dmalloc (sizeof *obj, MDL);
-       if (!obj)
-               return ISC_R_NOMEMORY;
-       memset (obj, 0, sizeof *obj);
-       obj -> refcnt = 1;
-       obj -> type = dhcp_type_failover_state;
+       obj = (dhcp_failover_state_t *)0;
+       dhcp_failover_state_allocate (&obj, MDL);
        obj -> listen_port = port;
        
        status = omapi_listen ((omapi_object_t *)obj, port, 1);
-       omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-       if (status != ISC_R_SUCCESS)
+       if (status != ISC_R_SUCCESS) {
+               dhcp_failover_state_dereference (&obj, MDL);
                return status;
+       }
 
        status = omapi_object_reference (&h -> outer, (omapi_object_t *)obj,
                                         MDL);
        if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
+               dhcp_failover_state_dereference (&obj, MDL);
                return status;
        }
        status = omapi_object_reference (&obj -> inner, h, MDL);
-       if (status != ISC_R_SUCCESS) {
-               omapi_object_dereference ((omapi_object_t **)&obj, MDL);
-               return status;
-       }
-
+       dhcp_failover_state_dereference (&obj, MDL);
        return status;
 }
 
@@ -1043,11 +1026,14 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
        if (!strcmp (name, "disconnect")) {
                link = va_arg (ap, dhcp_failover_link_t *);
 
-               omapi_object_dereference (&state -> link_to_peer, MDL);
+               dhcp_failover_link_dereference (&state -> link_to_peer, MDL);
                dhcp_failover_state_transition (state, "disconnect");
                if (state -> i_am == primary)
                        add_timeout (cur_time + 90, dhcp_failover_reconnect,
-                                    state); /* XXX this is a reference! */
+                                    state,
+                                    (tvref_t)dhcp_failover_state_reference,
+                                    (tvunref_t)
+                                    dhcp_failover_state_dereference);
        } else if (!strcmp (name, "message")) {
                link = va_arg (ap, dhcp_failover_link_t *);
 
@@ -1058,17 +1044,17 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
                        if (state -> link_to_peer) {
                                omapi_disconnect ((omapi_object_t *)
                                                  state -> link_to_peer, 1);
-                               omapi_object_dereference
+                               dhcp_failover_link_dereference
                                        (&state -> link_to_peer, MDL);
                                dhcp_failover_state_transition (state,
                                                                "disconnect");
                        }
-                       omapi_object_reference (&state -> link_to_peer,
-                                               (omapi_object_t *)link, MDL);
+                       dhcp_failover_link_reference (&state -> link_to_peer,
+                                                     link, MDL);
                        status = (dhcp_failover_send_connectack
                                  ((omapi_object_t *)link, 0));
                        if (status != ISC_R_SUCCESS) {
-                               omapi_object_dereference
+                               dhcp_failover_link_dereference
                                        (&state -> link_to_peer, MDL);
                                omapi_disconnect (link -> outer, 1);
                                return ISC_R_SUCCESS;
@@ -1126,8 +1112,8 @@ isc_result_t dhcp_failover_state_signal (omapi_object_t *o,
                                                       FTR_DUP_CONNECTION, 0);
                        omapi_disconnect (link -> outer, 0);
                    }
-                   omapi_object_reference (&state -> link_to_peer,
-                                           (omapi_object_t *)link, MDL);
+                   dhcp_failover_link_reference (&state -> link_to_peer,
+                                                 link, MDL);
                    dhcp_failover_state_transition (state, "connect");
                } else if (link -> imsg -> type == FTM_DISCONNECT) {
                    if (link -> imsg -> reject_reason) {
@@ -1274,28 +1260,17 @@ isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state,
            /* Now hook the ack queue to the beginning of the update
               queue. */
            if (state -> update_queue_head) {
-                   omapi_object_reference
-                           ((omapi_object_t **)
-                            &state -> ack_queue_tail -> next_pending,
-                            (omapi_object_t *)state -> update_queue_head,
-                            MDL);
-                   omapi_object_dereference ((omapi_object_t **)
-                                             &state -> update_queue_head,
-                                             MDL);
+                   lease_reference (&state -> ack_queue_tail -> next_pending,
+                                    state -> update_queue_head, MDL);
+                   lease_dereference (&state -> update_queue_head, MDL);
            }
-           omapi_object_reference ((omapi_object_t **)
-                                   &state -> update_queue_head,
-                                   (omapi_object_t *)state -> ack_queue_head,
-                                   MDL);
+           lease_reference (&state -> update_queue_head,
+                            state -> ack_queue_head, MDL);
            if (!state -> update_queue_tail)
-                   omapi_object_reference
-                           ((omapi_object_t **)
-                            &state -> update_queue_tail,
-                            (omapi_object_t *)state -> ack_queue_tail, MDL);
-           omapi_object_dereference ((omapi_object_t **)
-                                     &state -> ack_queue_tail, MDL);
-           omapi_object_dereference ((omapi_object_t **)
-                                     &state -> ack_queue_head, MDL);
+                   lease_reference (&state -> update_queue_tail,
+                                    state -> ack_queue_tail, MDL);
+           lease_dereference (&state -> ack_queue_tail, MDL);
+           lease_dereference (&state -> ack_queue_head, MDL);
            state -> cur_unacked_updates = 0;
        }
        cancel_timeout (dhcp_failover_keepalive, state);
@@ -1458,53 +1433,38 @@ isc_result_t dhcp_failover_send_updates (dhcp_failover_state_t *state)
        while (state -> max_flying_updates > state -> cur_unacked_updates &&
               state -> update_queue_head) {
                /* Grab the head of the update queue. */
-               omapi_object_reference ((omapi_object_t **)&lp,
-                                       (omapi_object_t *)
-                                       state -> update_queue_head, MDL);
+               lease_reference (&lp, state -> update_queue_head, MDL);
 
                /* Send the update to the peer. */
                status = dhcp_failover_send_bind_update (state, lp);
                if (status != ISC_R_SUCCESS) {
-                       omapi_object_dereference ((omapi_object_t **)&lp, MDL);
+                       lease_dereference (&lp, MDL);
                        return status;
                }
                lp -> flags &= ~ON_UPDATE_QUEUE;
 
                /* Take it off the head of the update queue and put the next
                   item in the update queue at the head. */
-               omapi_object_dereference ((omapi_object_t **)
-                                         &state -> update_queue_head, MDL);
+               lease_dereference (&state -> update_queue_head, MDL);
                if (lp -> next_pending) {
-                       omapi_object_reference ((omapi_object_t **)
-                                               &state -> update_queue_head,
-                                               (omapi_object_t *)
-                                               lp -> next_pending, MDL);
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &lp -> next_pending, MDL);
+                       lease_reference (&state -> update_queue_head,
+                                        lp -> next_pending, MDL);
+                       lease_dereference (&lp -> next_pending, MDL);
                } else {
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &state -> update_queue_tail,
-                                                 MDL);
+                       lease_dereference (&state -> update_queue_tail, MDL);
                }
 
                if (state -> ack_queue_head) {
-                       omapi_object_reference
-                               ((omapi_object_t **)
-                                &state -> ack_queue_tail -> next_pending,
-                                (omapi_object_t *)lp, MDL);
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &state -> ack_queue_tail,
-                                                 MDL);
+                       lease_reference
+                               (&state -> ack_queue_tail -> next_pending,
+                                lp, MDL);
+                       lease_dereference (&state -> ack_queue_tail, MDL);
                } else {
-                       omapi_object_reference ((omapi_object_t **)
-                                               &state -> ack_queue_head,
-                                               (omapi_object_t *)lp, MDL);
+                       lease_reference (&state -> ack_queue_head, lp, MDL);
                }
-               omapi_object_reference ((omapi_object_t **)
-                                       &state -> ack_queue_tail,
-                                       (omapi_object_t *)lp, MDL);
+               lease_reference (&state -> ack_queue_tail, lp, MDL);
                lp -> flags |= ON_ACK_QUEUE;
-               omapi_object_dereference ((omapi_object_t **)&lp, MDL);
+               lease_dereference (&lp, MDL);
 
                /* Count the object as an unacked update. */
                state -> cur_unacked_updates++;
@@ -1536,20 +1496,17 @@ int dhcp_failover_queue_update (struct lease *lease)
                dhcp_failover_ack_queue_remove (state, lease);
 
        if (state -> update_queue_head) {
-               omapi_object_reference
-                       ((omapi_object_t **)
-                        &state -> update_queue_tail -> next_pending,
-                        (omapi_object_t *)lease, MDL);
-               omapi_object_dereference ((omapi_object_t **)
-                                         &state -> update_queue_tail, MDL);
+               if (state -> update_queue_tail -> next_pending)
+                       lease_dereference
+                               (&state -> update_queue_tail -> next_pending,
+                                MDL);
+               lease_reference (&state -> update_queue_tail -> next_pending,
+                                lease, MDL);
+               lease_dereference (&state -> update_queue_tail, MDL);
        } else {
-               omapi_object_reference ((omapi_object_t **)
-                                       &state -> update_queue_head,
-                                       (omapi_object_t *)lease, MDL);
+               lease_reference (&state -> update_queue_head, lease, MDL);
        }
-       omapi_object_reference ((omapi_object_t **)
-                               &state -> update_queue_tail,
-                               (omapi_object_t *)lease, MDL);
+       lease_reference (&state -> update_queue_tail, lease, MDL);
        lease -> flags |= ON_UPDATE_QUEUE;
        dhcp_failover_send_updates (state);
        return 1;
@@ -1561,17 +1518,12 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
        struct lease *lp;
 
        if (state -> ack_queue_head == lease) {
-               omapi_object_dereference ((omapi_object_t **)
-                                         &state -> ack_queue_head, MDL);
+               lease_dereference (&state -> ack_queue_head, MDL);
                if (lease -> next_pending) {
-                       omapi_object_reference ((omapi_object_t **)
-                                               &state -> ack_queue_head,
-                                               (omapi_object_t *)
-                                               lease -> next_pending, MDL);
+                       lease_reference (&state -> ack_queue_head,
+                                        lease -> next_pending, MDL);
                } else {
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &state -> ack_queue_tail,
-                                                 MDL);
+                       lease_dereference (&state -> ack_queue_tail, MDL);
                }
                lease -> flags &= ~ON_ACK_QUEUE;
                return;
@@ -1580,20 +1532,13 @@ void dhcp_failover_ack_queue_remove (dhcp_failover_state_t *state,
             lp -> next_pending != lease; lp = lp -> next_pending)
                ;
        if (lp) {
-               omapi_object_dereference ((omapi_object_t **)
-                                         &lp -> next_pending, MDL);
+               lease_dereference (&lp -> next_pending, MDL);
                if (lease -> next_pending)
-                       omapi_object_reference ((omapi_object_t **)
-                                               &lp -> next_pending,
-                                               (omapi_object_t *)
-                                               lease -> next_pending, MDL);
+                       lease_reference (&lp -> next_pending,
+                                        lease -> next_pending, MDL);
                else {
-                       omapi_object_dereference ((omapi_object_t **)
-                                                 &state -> ack_queue_tail,
-                                                 MDL);
-                       omapi_object_reference ((omapi_object_t **)
-                                               &state -> ack_queue_tail,
-                                               (omapi_object_t *)lp, MDL);
+                       lease_dereference (&state -> ack_queue_tail, MDL);
+                       lease_reference (&state -> ack_queue_tail, lp, MDL);
                }
        }
        lease -> flags &= ~ON_ACK_QUEUE;
@@ -1628,7 +1573,9 @@ void dhcp_failover_reconnect (void *vs)
                log_info ("failover peer %s: %s", state -> name,
                          isc_result_totext (status));
                add_timeout (cur_time + 90,
-                            dhcp_failover_listener_restart, state);
+                            dhcp_failover_listener_restart, state,
+                            (tvref_t)dhcp_failover_state_reference,
+                            (tvunref_t)dhcp_failover_state_dereference);
        }
 }
 
@@ -1642,7 +1589,9 @@ void dhcp_failover_listener_restart (void *vs)
                log_info ("failover peer %s: %s", state -> name,
                          isc_result_totext (status));
                add_timeout (cur_time + 90,
-                            dhcp_failover_listener_restart, state);
+                            dhcp_failover_listener_restart, state,
+                            (tvref_t)dhcp_failover_state_reference,
+                            (tvunref_t)dhcp_failover_state_dereference);
        }
 }
 
@@ -1753,7 +1702,7 @@ isc_result_t dhcp_failover_state_destroy (omapi_object_t *h,
                return ISC_R_INVALIDARG;
        s = (dhcp_failover_state_t *)h;
        if (s -> link_to_peer)
-               omapi_object_dereference (&s -> link_to_peer, MDL);
+               dhcp_failover_link_dereference (&s -> link_to_peer, MDL);
        if (s -> name)
                dfree (s -> name, MDL);
        if (s -> address)
@@ -2947,64 +2896,69 @@ isc_result_t dhcp_failover_send_poolresp (dhcp_failover_state_t *state,
 isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
                                               failover_message_t *msg)
 {
-       struct lease lt, *lease;
+       struct lease *lt, *lease;
        struct iaddr ia;
+       int reason = FTR_MISC_REJECT;
+       const char *message;
 
        ia.len = sizeof msg -> assigned_addr;
        memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
 
-       lease = find_lease_by_ip_addr (ia);
-       if (!lease) {
-               log_info ("bind update on %s from %s: no such lease.",
-                         piaddr (ia), state -> name);
-               return ISC_R_SUCCESS;
+       lease = (struct lease *)0;
+       if (!find_lease_by_ip_addr (&lease, ia, MDL)) {
+               message = "unknown IP address";
+               reason = FTR_ILLEGAL_IP_ADDR;
+               goto bad;
        }
 
        /* XXX check for conflicts. */
 
        /* Install the new info. */
-       lt = *lease;
-       lt.on_expiry = 0;
-       lt.on_release = 0;
-       lt.on_commit = 0;
+       lt = (struct lease *)0;
+       if (!lease_copy (&lt, lease, MDL)) {
+               message = "no memory";
+               goto bad;
+       }
 
        if (msg -> options_present & FTB_CHADDR) {
-               if (msg -> chaddr.count > sizeof lt.hardware_addr.hbuf) {
-                       log_info ("bind update on %s from %s: chaddr too long",
-                                 piaddr (ia), state -> name);
-                       return ISC_R_SUCCESS;
+               if (msg -> chaddr.count > sizeof lt -> hardware_addr.hbuf) {
+                       message = "chaddr to long";
+                       goto bad;
                }
-               lt.hardware_addr.hlen = msg -> chaddr.count;
-               memcpy (lt.hardware_addr.hbuf, msg -> chaddr.data,
+               lt -> hardware_addr.hlen = msg -> chaddr.count;
+               memcpy (lt -> hardware_addr.hbuf, msg -> chaddr.data,
                        msg -> chaddr.count);
        }               
 
        if (msg -> options_present & FTB_CLIENT_IDENTIFIER) {
-               lt.uid_len = msg -> client_identifier.count;
-               if (lt.uid_len > sizeof lt.uid_buf) {
-                       lt.uid_max = lt.uid_len;
-                       lt.uid = dmalloc (lt.uid_len, MDL);
-                       if (!lt.uid)
-                               return ISC_R_SUCCESS;
+               lt -> uid_len = msg -> client_identifier.count;
+               if (lt -> uid_len > sizeof lt -> uid_buf) {
+                       lt -> uid_max = lt -> uid_len;
+                       lt -> uid = dmalloc (lt -> uid_len, MDL);
+                       if (!lt -> uid) {
+                               message = "no memory";
+                               goto bad;
+                       }
                } else {
-                       lt.uid_max = sizeof lt.uid_buf;
-                       lt.uid = lt.uid_buf;
+                       lt -> uid_max = sizeof lt -> uid_buf;
+                       lt -> uid = lt -> uid_buf;
                }
-               memcpy (lt.uid, msg -> client_identifier.data, lt.uid_len);
+               memcpy (lt -> uid,
+                       msg -> client_identifier.data, lt -> uid_len);
        }
                
        /* XXX Times may need to be adjusted based on clock skew! */
        if (msg -> options_present & FTB_STOS) {
-               lt.starts = msg -> stos;
+               lt -> starts = msg -> stos;
        }
        if (msg -> options_present & FTB_LEASE_EXPIRY) {
-               lt.ends = msg -> expiry;
+               lt -> ends = msg -> expiry;
        }
        if (msg -> options_present & FTB_CLTT) {
-               lt.cltt = msg -> client_ltt;
+               lt -> cltt = msg -> client_ltt;
        }
        if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
-               lt.tsfp = msg -> potential_expiry;
+               lt -> tsfp = msg -> potential_expiry;
        }
 
        if (msg -> options_present & FTB_BINDING_STATUS) {
@@ -3022,12 +2976,16 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
        }
 
        /* Try to install the new information. */
-       if (!supersede_lease (lease, &lt, 1, 0)) {
+       if (!supersede_lease (lease, lt, 1, 0)) {
+               message = "database update failed";
+             bad:
                dhcp_failover_send_bind_ack (state, lease, msg,
-                                            FTR_MISC_REJECT,
-                                            "database update failed.");
+                                            reason, message);
        } else
                dhcp_failover_send_bind_ack (state, lease, msg, 0, 0);
+       if (lt)
+               lease_dereference (&lt, MDL);
+       lease_dereference (&lease, MDL);
 
        return ISC_R_SUCCESS;
 }
@@ -3035,34 +2993,34 @@ isc_result_t dhcp_failover_process_bind_update (dhcp_failover_state_t *state,
 isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
                                             failover_message_t *msg)
 {
-       struct lease lt, *lease;
+       struct lease *lt, *lease = (struct lease *)0;
        struct iaddr ia;
+       const char *message = "no memory";
 
        ia.len = sizeof msg -> assigned_addr;
        memcpy (ia.iabuf, &msg -> assigned_addr, ia.len);
 
-       lease = find_lease_by_ip_addr (ia);
-       if (!lease) {
-               log_info ("bind update on %s from %s: no such lease.",
-                         piaddr (ia), state -> name);
-               return ISC_R_SUCCESS;
+       if (!find_lease_by_ip_addr (&lease, ia, MDL)) {
+               message = "no such lease";
+               goto bad;
        }
 
        /* XXX check for conflicts. */
 
        /* Install the new info. */
-       lt = *lease;
-       lt.on_expiry = 0;
-       lt.on_release = 0;
-       lt.on_commit = 0;
+       lt = (struct lease *)0;
+       if (!lease_copy (&lt, lease, MDL)) {
+               lease_dereference (&lease, MDL);
+               goto bad;
+       }
 
        /* XXX Times may need to be adjusted based on clock skew! */
        if (msg -> options_present & FTB_POTENTIAL_EXPIRY) {
-               lt.tsfp = msg -> potential_expiry;
+               lt -> tsfp = msg -> potential_expiry;
        }
 
        /* Try to install the new information. */
-       supersede_lease (lease, &lt, 1, 0);
+       supersede_lease (lease, lt, 1, 0);
 
        state -> cur_unacked_updates--;
        dhcp_failover_ack_queue_remove (state, lease);
@@ -3071,7 +3029,17 @@ isc_result_t dhcp_failover_process_bind_ack (dhcp_failover_state_t *state,
           least one. */
        dhcp_failover_send_updates (state);
 
+      out:
+       lease_dereference (&lease, MDL);
+       if (lt)
+               lease_dereference (&lt, MDL);
+
        return ISC_R_SUCCESS;
+
+      bad:
+       log_info ("bind update on %s from %s: %s.",
+                 piaddr (ia), state -> name, message);
+       goto out;
 }
 
 #if defined (DEBUG_FAILOVER_MESSAGES)
@@ -3168,4 +3136,11 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state)
        else
                return !hm;
 }
+
+OMAPI_OBJECT_ALLOC (dhcp_failover_state, dhcp_failover_state_t,
+                   dhcp_type_failover_state)
+OMAPI_OBJECT_ALLOC (dhcp_failover_listener, dhcp_failover_listener_t,
+                   dhcp_type_failover_listener)
+OMAPI_OBJECT_ALLOC (dhcp_failover_link, dhcp_failover_link_t,
+                   dhcp_type_failover_link)
 #endif /* defined (FAILOVER_PROTOCOL) */
index 1803e38d7fdbde27f18b3510357077fb6d1052ee..c6b28978f2b24fa4675442a50d5e86eafd853717 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: mdb.c,v 1.31 2000/05/04 18:58:16 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: mdb.c,v 1.32 2000/05/16 23:03:46 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -58,8 +58,6 @@ struct hash_table *lease_hw_addr_hash;
 struct hash_table *host_name_hash;
 static struct lease *dangling_leases;
 
-struct hash_table *group_name_hash;
-
 omapi_object_type_t *dhcp_type_host;
 
 isc_result_t enter_host (hd, dynamicp, commit)
@@ -72,20 +70,21 @@ isc_result_t enter_host (hd, dynamicp, commit)
        struct executable_statement *esp;
 
        if (!host_name_hash) {
-               host_name_hash = new_hash (0, 0, 0);
+               host_name_hash =
+                       new_hash ((hash_reference)host_reference,
+                                 (hash_dereference)host_dereference, 0);
                if (!host_name_hash)
                        log_fatal ("Can't allocate host name hash");
        } else {
-               hp = (struct host_decl *)
-                       hash_lookup (host_name_hash,
-                                    (unsigned char *)hd -> name,
-                                    strlen (hd -> name));
+               host_hash_lookup (&hp, host_name_hash,
+                                 (unsigned char *)hd -> name,
+                                 strlen (hd -> name), MDL);
 
                /* If it's deleted, we can supersede it. */
                if (hp && (hp -> flags & HOST_DECL_DELETED)) {
-                       delete_hash_entry (host_name_hash,
-                                          (unsigned char *)hd -> name,
-                                          strlen (hd -> name));
+                       host_hash_delete (host_name_hash,
+                                         (unsigned char *)hd -> name,
+                                         strlen (hd -> name), MDL);
                        /* If the old entry wasn't dynamic, then we
                           always have to keep the deletion. */
                        if (!hp -> flags & HOST_DECL_DYNAMIC)
@@ -95,40 +94,42 @@ isc_result_t enter_host (hd, dynamicp, commit)
                /* If there isn't already a host decl matching this
                   address, add it to the hash table. */
                if (!hp) {
-                       add_hash (host_name_hash,
-                                 (unsigned char *)hd -> name,
-                                 strlen (hd -> name),
-                                 (unsigned char *)hd);
-                       hd -> refcnt++; /* XXX */
-               } else
+                       host_hash_add (host_name_hash,
+                                      (unsigned char *)hd -> name,
+                                      strlen (hd -> name), hd, MDL);
+               } else {
                        /* XXX actually, we have to delete the old one
                           XXX carefully and replace it.   Not done yet. */
+                       host_dereference (&hp, MDL);
                        return ISC_R_EXISTS;
+               }
        }
 
-       hd -> n_ipaddr = (struct host_decl *)0;
+       if (hd -> n_ipaddr)
+               host_dereference (&hd -> n_ipaddr, MDL);
 
        if (!hd -> type)
                hd -> type = dhcp_type_host;
 
        if (hd -> interface.hlen) {
                if (!host_hw_addr_hash) {
-                       host_hw_addr_hash = new_hash (0, 0, 0);
+                       host_hw_addr_hash =
+                               new_hash ((hash_reference)host_reference,
+                                         (hash_dereference)host_dereference,
+                                         0);
                        if (!host_hw_addr_hash)
                                log_fatal ("Can't allocate host/hw hash");
-               } else
-                       hp = (struct host_decl *)
-                               hash_lookup (host_hw_addr_hash,
-                                            hd -> interface.hbuf,
-                                            hd -> interface.hlen);
-
-               /* If there isn't already a host decl matching this
-                  address, add it to the hash table. */
-               if (!hp) {
-                       add_hash (host_hw_addr_hash,
-                                 hd -> interface.hbuf, hd -> interface.hlen,
-                                 (unsigned char *)hd);
-                       hd -> refcnt++; /* XXX */
+               } else {
+                       /* If there isn't already a host decl matching this
+                          address, add it to the hash table. */
+                       if (!host_hash_lookup (&hp, host_hw_addr_hash,
+                                              hd -> interface.hbuf,
+                                              hd -> interface.hlen, MDL)) {
+                               host_hash_add (host_hw_addr_hash,
+                                              hd -> interface.hbuf,
+                                              hd -> interface.hlen,
+                                              hd, MDL);
+                       }
                }
        }
 
@@ -138,8 +139,8 @@ isc_result_t enter_host (hd, dynamicp, commit)
        if (hp) {
                for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
                        ;
-               np -> n_ipaddr = hd;
-               hd -> refcnt++; /* XXX */
+               host_reference (&np -> n_ipaddr, hd, MDL);
+               host_dereference (&hp, MDL);
        }
 
        /* See if there's a statement that sets the client identifier.
@@ -167,34 +168,35 @@ isc_result_t enter_host (hd, dynamicp, commit)
                /* If there's no uid hash, make one; otherwise, see if
                   there's already an entry in the hash for this host. */
                if (!host_uid_hash) {
-                       host_uid_hash = new_hash (0, 0, 0);
+                       host_uid_hash =
+                               new_hash ((hash_reference)host_reference,
+                                         (hash_dereference)host_dereference,
+                                         0);
                        if (!host_uid_hash)
                                log_fatal ("Can't allocate host/uid hash");
-                       hp = (struct host_decl *)0;
-               } else
-                       hp = ((struct host_decl *)
-                             hash_lookup (host_uid_hash,
-                                          hd -> client_identifier.data,
-                                          hd -> client_identifier.len));
-
-               /* If there's already a host declaration for this
-                  client identifier, add this one to the end of the
-                  list.  Otherwise, add it to the hash table. */
-               if (hp) {
-                       /* Don't link it in twice... */
-                       if (!np) {
-                               for (np = hp; np -> n_ipaddr;
-                                    np = np -> n_ipaddr)
-                                       ;
-                               np -> n_ipaddr = hd;
-                               hd -> refcnt++; /* XXX */
-                       }
                } else {
-                       add_hash (host_uid_hash,
-                                 hd -> client_identifier.data,
-                                 hd -> client_identifier.len,
-                                 (unsigned char *)hd);
-                       hd -> refcnt++; /* XXX */
+                       /* If there's already a host declaration for this
+                          client identifier, add this one to the end of the
+                          list.  Otherwise, add it to the hash table. */
+                       if (host_hash_lookup (&hp, host_uid_hash,
+                                             hd -> client_identifier.data,
+                                             hd -> client_identifier.len,
+                                             MDL)) {
+                               /* Don't link it in twice... */
+                               if (!np) {
+                                       for (np = hp; np -> n_ipaddr;
+                                            np = np -> n_ipaddr)
+                                               ;
+                                       host_reference (&np -> n_ipaddr,
+                                                       hd, MDL);
+                               }
+                               host_dereference (&hp, MDL);
+                       } else {
+                               host_hash_add (host_uid_hash,
+                                              hd -> client_identifier.data,
+                                              hd -> client_identifier.len,
+                                              hd, MDL);
+                       }
                }
        }
 
@@ -214,6 +216,7 @@ isc_result_t delete_host (hd, commit)
 {
        struct host_decl *hp = (struct host_decl *)0;
        struct host_decl *np = (struct host_decl *)0;
+       struct host_decl *foo;
        struct executable_statement *esp;
        int hw_head = 0, uid_head = 1;
 
@@ -225,99 +228,90 @@ isc_result_t delete_host (hd, commit)
        hd -> flags |= HOST_DECL_DELETED;
 
        if (hd -> interface.hlen) {
-               if (host_hw_addr_hash) {
-                       hp = (struct host_decl *)
-                               hash_lookup (host_hw_addr_hash,
-                                            hd -> interface.hbuf,
-                                            hd -> interface.hlen);
-
-                       if (hp) {
-                               if (hp == hd) {
-                                   delete_hash_entry
-                                           (host_hw_addr_hash,
-                                            hd -> interface.hbuf,
-                                            hd -> interface.hlen);
-                                   hw_head = 1;
-                                   --hd -> refcnt;
-                               }
-                       } else {
-                               for (; hp; hp = hp -> n_ipaddr) {
-                                       np = hp;
-                                       if (hp == hd)
-                                               break;
-                               }
-                               if (hp) {
-                                       np -> n_ipaddr = hd -> n_ipaddr;
-                                       hd -> refcnt--;
-                               }
+           if (host_hw_addr_hash) {
+               if (host_hash_lookup (&hp, host_hw_addr_hash,
+                       hd -> interface.hbuf,
+                       hd -> interface.hlen, MDL)) {
+                   if (hp == hd) {
+                       host_hash_delete (host_hw_addr_hash,
+                                         hd -> interface.hbuf,
+                                         hd -> interface.hlen, MDL);
+                       hw_head = 1;
+                   } else {
+                       for (foo = hp; foo; foo = foo -> n_ipaddr) {
+                           if (foo == hd)
+                                   break;
+                           np = foo;
+                       }
+                       if (foo) {
+                           host_dereference (&np -> n_ipaddr, MDL);
+                           if (hd -> n_ipaddr)
+                               host_reference (&np -> n_ipaddr,
+                                               hd -> n_ipaddr, MDL);
                        }
+                   }
+                   host_dereference (&hp, MDL);
                }
+           }
        }
 
        /* If we got a client identifier, hash this entry by
           client identifier. */
        if (hd -> client_identifier.len) {
-               if (host_uid_hash) {
-                       hp = (struct host_decl *)
-                               hash_lookup (host_uid_hash,
-                                            hd -> client_identifier.data,
-                                            hd -> client_identifier.len);
-
-                       if (hp) {
-                               if (hp == hd) {
-                                   delete_hash_entry
-                                           (host_uid_hash,
-                                            hd -> client_identifier.data,
-                                            hd -> client_identifier.len);
-                                   uid_head = 1;
-                                   --hd -> refcnt;
-                               }
-                       } else {
-                               for (; hp; hp = hp -> n_ipaddr) {
-                                       np = hp;
-                                       if (hp == hd)
-                                               break;
-                               }
-                               if (hp) {
-                                       np -> n_ipaddr = hd -> n_ipaddr;
-                                       hd -> refcnt--;
-                               }
+           if (host_uid_hash) {
+               if (host_hash_lookup (&hp, host_uid_hash,
+                                     hd -> client_identifier.data,
+                                     hd -> client_identifier.len, MDL)) {
+                   if (hp == hd) {
+                       host_hash_delete (host_uid_hash,
+                                         hd -> client_identifier.data,
+                                         hd -> client_identifier.len, MDL);
+                       uid_head = 1;
+                   } else {
+                       for (foo = hp; foo; foo = foo -> n_ipaddr) {
+                           if (foo == hd)
+                               break;
+                           np = foo;
+                       }
+                       if (foo) {
+                           if (np -> n_ipaddr)
+                               host_dereference (&np -> n_ipaddr, MDL);
+                           host_reference (&np -> n_ipaddr,
+                                           hd -> n_ipaddr, MDL);
                        }
+                   }
+                   host_dereference (&hp, MDL);
                }
+           }
        }
 
        if (hd -> n_ipaddr) {
                if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
-                       add_hash (host_uid_hash,
-                                 hd -> n_ipaddr -> client_identifier.data,
-                                 hd -> n_ipaddr -> client_identifier.len,
-                                 (unsigned char *)hd -> n_ipaddr);
-                       hd -> n_ipaddr -> refcnt++;
+                       host_hash_add
+                               (host_uid_hash,
+                                hd -> n_ipaddr -> client_identifier.data,
+                                hd -> n_ipaddr -> client_identifier.len,
+                                hd -> n_ipaddr, MDL);
                }
                if (hw_head && hd -> n_ipaddr -> interface.hlen) {
-                       add_hash (host_hw_addr_hash,
-                                 hd -> n_ipaddr -> interface.hbuf,
-                                 hd -> n_ipaddr -> interface.hlen,
-                                 (unsigned char *)hd -> n_ipaddr);
-                       hd -> n_ipaddr -> refcnt++;
+                       host_hash_add (host_hw_addr_hash,
+                                      hd -> n_ipaddr -> interface.hbuf,
+                                      hd -> n_ipaddr -> interface.hlen,
+                                      hd -> n_ipaddr, MDL);
                }
-               omapi_object_dereference ((omapi_object_t **)&hd -> n_ipaddr,
-                                         MDL);
+               host_dereference (&hd -> n_ipaddr, MDL);
        }
 
        if (host_name_hash) {
-               hp = (struct host_decl *)
-                       hash_lookup (host_name_hash,
-                                    (unsigned char *)hd -> name,
-                                    strlen (hd -> name));
-               
-               if (hp) {
+               if (host_hash_lookup (&hp, host_name_hash,
+                                     (unsigned char *)hd -> name,
+                                     strlen (hd -> name), MDL)) {
                        if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
-                               delete_hash_entry (host_name_hash,
-                                                  (unsigned char *)hd -> name,
-                                                  strlen (hd -> name));
-                               --hd -> refcnt;
+                               host_hash_delete (host_name_hash,
+                                                 (unsigned char *)hd -> name,
+                                                 strlen (hd -> name), MDL);
                        }
+                       host_dereference (&hp, MDL);
                }
        }
 
@@ -330,10 +324,9 @@ isc_result_t delete_host (hd, commit)
        return ISC_R_SUCCESS;
 }
 
-struct host_decl *find_hosts_by_haddr (htype, haddr, hlen)
-       int htype;
-       const unsigned char *haddr;
-       unsigned hlen;
+int find_hosts_by_haddr (struct host_decl **hp, int htype,
+                        const unsigned char *haddr, unsigned hlen,
+                        const char *file, int line)
 {
        struct host_decl *foo;
        struct hardware h;
@@ -342,19 +335,15 @@ struct host_decl *find_hosts_by_haddr (htype, haddr, hlen)
        h.hbuf [0] = htype;
        memcpy (&h.hbuf [1], haddr, hlen);
 
-       foo = (struct host_decl *)hash_lookup (host_hw_addr_hash,
-                                              h.hbuf, h.hlen);
-       return foo;
+       return host_hash_lookup (hp, host_hw_addr_hash,
+                                h.hbuf, h.hlen, file, line);
 }
 
-struct host_decl *find_hosts_by_uid (data, len)
-       const unsigned char *data;
-       unsigned len;
+int find_hosts_by_uid (struct host_decl **hp,
+                      const unsigned char *data, unsigned len,
+                      const char *file, int line)
 {
-       struct host_decl *foo;
-
-       foo = (struct host_decl *)hash_lookup (host_uid_hash, data, len);
-       return foo;
+       return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
 }
 
 /* More than one host_decl can be returned by find_hosts_by_haddr or
@@ -365,10 +354,8 @@ struct host_decl *find_hosts_by_uid (data, len)
    the addr pointer, update the host pointer to point at the host_decl
    that matched, and return the subnet that matched. */
 
-struct subnet *find_host_for_network (host, addr, share)
-       struct host_decl **host;
-       struct iaddr *addr;
-       struct shared_network *share;
+int find_host_for_network (struct subnet **sp, struct host_decl **host,
+                          struct iaddr *addr, struct shared_network *share)
 {
        int i;
        struct subnet *subnet;
@@ -392,126 +379,25 @@ struct subnet *find_host_for_network (host, addr, share)
                        ip_address.len = 4;
                        memcpy (ip_address.iabuf,
                                fixed_addr.data + i, 4);
-                       subnet = find_grouped_subnet (share, ip_address);
-                       if (subnet) {
+                       if (find_grouped_subnet (sp, share, ip_address, MDL)) {
+                               struct host_decl *tmp = (struct host_decl *)0;
                                *addr = ip_address;
-                               *host = hp;
+                               /* This is probably not necessary, but
+                                  just in case *host is the only reference
+                                  to that host declaration, make a temporary
+                                  reference so that dereferencing it doesn't
+                                  dereference hp out from under us. */
+                               host_reference (&tmp, *host, MDL);
+                               host_dereference (host, MDL);
+                               host_reference (host, hp, MDL);
+                               host_dereference (&tmp, MDL);
                                data_string_forget (&fixed_addr, MDL);
-                               return subnet;
+                               return 1;
                        }
                }
                data_string_forget (&fixed_addr, MDL);
        }
-       return (struct subnet *)0;
-}
-
-isc_result_t delete_group (struct group_object *group, int writep)
-{
-       struct group_object *d;
-
-       /* The group should exist and be hashed - if not, it's invalid. */
-       if (group_name_hash)
-               d = ((struct group_object *)
-                    hash_lookup (group_name_hash,
-                                 (unsigned char *)group -> name,
-                                 strlen (group -> name)));
-       else
-               return ISC_R_INVALIDARG;
-       if (!d)
-               return ISC_R_INVALIDARG;
-
-       /* Also not okay to delete a group that's not the one in
-          the hash table. */
-       if (d != group)
-               return ISC_R_INVALIDARG;
-
-       /* If it's dynamic, and we're deleting it, we can just blow away the
-          hash table entry. */
-       if ((group -> flags & GROUP_OBJECT_DYNAMIC) &&
-           !(group -> flags & GROUP_OBJECT_STATIC)) {
-               delete_hash_entry (group_name_hash,
-                                  (unsigned char *)group -> name,
-                                  strlen (group -> name));
-                       --group -> refcnt;
-       } else {
-               group -> flags |= GROUP_OBJECT_DELETED;
-               if (group -> group) {
-                       dfree (group -> group, MDL);
-                       group -> group = (struct group *)0;
-               }
-       }
-
-       /* Store the group declaration in the lease file. */
-       if (writep) {
-               if (!write_group (group))
-                       return ISC_R_IOERROR;
-               if (!commit_leases ())
-                       return ISC_R_IOERROR;
-       }
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t supersede_group (struct group_object *group, int writep)
-{
-       struct group_object *t, *u;
-       isc_result_t status;
-
-       /* Register the group in the group name hash table,
-          so we can look it up later. */
-       if (group_name_hash) {
-               t = ((struct group_object *)
-                    hash_lookup (group_name_hash,
-                                 (unsigned char *)group -> name,
-                                 strlen (group -> name)));
-               if (t && t != group) {
-                       /* If this isn't a dynamic entry, then we need to flag
-                          the replacement as not dynamic either - otherwise,
-                          if the dynamic entry is deleted later, the static
-                          entry will come back next time the server is stopped
-                          and restarted. */
-                       if (!(t -> flags & GROUP_OBJECT_DYNAMIC))
-                               group -> flags |= GROUP_OBJECT_STATIC;
-
-                       /* Delete the old object if it hasn't already been
-                          deleted.  If it has already been deleted, get rid of
-                          the hash table entry.  This is a legitimate
-                          situation - a deleted static object needs to be kept
-                          around so we remember it's deleted. */
-                       if (!(t -> flags & GROUP_OBJECT_DELETED))
-                               delete_group (t, 0);
-                       else {
-                               delete_hash_entry
-                                       (group_name_hash,
-                                        (unsigned char *)group -> name,
-                                        strlen (group -> name));
-                               omapi_object_dereference
-                                       ((omapi_object_t **)&t, MDL);
-                       }
-               }
-       } else {
-               group_name_hash = new_hash (0, 0, 0);
-               t = (struct group_object *)0;
-       }
-
-       /* Add the group to the group name hash if it's not
-          already there, and also thread it into the list of
-          dynamic groups if appropriate. */
-       if (!t) {
-               add_hash (group_name_hash,
-                         (unsigned char *)group -> name,
-                         strlen (group -> name),
-                         (unsigned char *)group);
-       }
-
-       /* Store the group declaration in the lease file. */
-       if (writep) {
-               if (!write_group (group))
-                       return ISC_R_IOERROR;
-               if (!commit_leases ())
-                       return ISC_R_IOERROR;
-       }
-
-       return ISC_R_SUCCESS;
+       return 0;
 }
 
 void new_address_range (low, high, subnet, pool)
@@ -524,6 +410,7 @@ void new_address_range (low, high, subnet, pool)
        unsigned min, max, i;
        char lowbuf [16], highbuf [16], netbuf [16];
        struct shared_network *share = subnet -> shared_network;
+       isc_result_t status;
 
        /* All subnets should have attached shared network structures. */
        if (!share) {
@@ -534,17 +421,23 @@ void new_address_range (low, high, subnet, pool)
 
        /* Initialize the hash table if it hasn't been done yet. */
        if (!lease_uid_hash) {
-               lease_uid_hash = new_hash (0, 0, 0);
+               lease_uid_hash =
+                       new_hash ((hash_reference)lease_reference,
+                                 (hash_dereference)lease_dereference, 0);
                if (!lease_uid_hash)
                        log_fatal ("Can't allocate lease/uid hash");
        }
        if (!lease_ip_addr_hash) {
-               lease_ip_addr_hash = new_hash (0, 0, 0);
+               lease_ip_addr_hash =
+                       new_hash ((hash_reference)lease_reference,
+                                 (hash_dereference)lease_dereference, 0);
                if (!lease_uid_hash)
                        log_fatal ("Can't allocate lease/ip hash");
        }
        if (!lease_hw_addr_hash) {
-               lease_hw_addr_hash = new_hash (0, 0, 0);
+               lease_hw_addr_hash =
+                       new_hash ((hash_reference)lease_reference,
+                                 (hash_dereference)lease_dereference, 0);
                if (!lease_uid_hash)
                        log_fatal ("Can't allocate lease/hw hash");
        }
@@ -579,6 +472,7 @@ void new_address_range (low, high, subnet, pool)
        }
 
        /* Get a lease structure for each address in the range. */
+#if defined (COMPACT_LEASES)
        address_range = new_leases (max - min + 1, MDL);
        if (!address_range) {
                strcpy (lowbuf, piaddr (low));
@@ -586,44 +480,62 @@ void new_address_range (low, high, subnet, pool)
                log_fatal ("No memory for address range %s-%s.",
                           lowbuf, highbuf);
        }
-       memset (address_range, 0, (sizeof *address_range) * (max - min + 1));
-
-       /* Fill in the last lease if it hasn't been already... */
-       if (!pool -> last_lease) {
-               pool -> last_lease = &address_range [0];
-       }
+#endif
 
        /* Fill out the lease structures with some minimal information. */
        for (i = 0; i < max - min + 1; i++) {
-               address_range [i].ip_addr =
-                       ip_addr (subnet -> net, subnet -> netmask, i + min);
-               address_range [i].starts =
-                       address_range [i].timestamp = MIN_TIME;
-               address_range [i].ends = MIN_TIME;
-               address_range [i].subnet = subnet;
-               address_range [i].pool = pool;
-               address_range [i].billing_class = (struct class *)0;
+               struct lease *lp = (struct lease *)0;
+#if defined (COMPACT_LEASES)
+               omapi_object_initialize ((omapi_object_t *)&address_range [i],
+                                        dhcp_type_lease,
+                                        0, sizeof (struct lease), MDL);
+               lease_reference (&lp, &address_range [i], MDL);
+#else
+               status = lease_allocate (&lp, MDL);
+               if (status != ISC_R_SUCCESS)
+                       log_fatal ("No memory for lease %s: %s",
+                                  piaddr (ip_addr (subnet -> net,
+                                                   subnet -> netmask,
+                                                   i + min)),
+                                  isc_result_totext (status));
+               /* Fill in the last lease if it hasn't been already... */
+               if (!pool -> last_lease) {
+                       lease_reference (&pool -> last_lease, lp, MDL);
+               }
+#endif
+               lp -> ip_addr = ip_addr (subnet -> net,
+                                     subnet -> netmask, i + min);
+               lp -> starts = lp -> timestamp = MIN_TIME;
+               lp -> ends = MIN_TIME;
+               subnet_reference (&lp -> subnet, subnet, MDL);
+               pool_reference (&lp -> pool, pool, MDL);
 #if defined (FAILOVER_PROTOCOL)
                if (pool -> failover_peer &&
                    pool -> failover_peer -> i_am == secondary)
-                       address_range [i].flags = PEER_IS_OWNER;
+                       lp -> flags = PEER_IS_OWNER;
                else
-                       address_range [i].flags = 0;
+                       lp -> flags = 0;
 #endif
-               address_range [i].type = dhcp_type_lease;
 
                /* Link this entry into the list. */
-               address_range [i].next = pool -> leases;
-               address_range [i].prev = (struct lease *)0;
-               pool -> leases = &address_range [i];
-               if (address_range [i].next)
-                       address_range [i].next -> prev = pool -> leases;
-               add_hash (lease_ip_addr_hash,
-                         address_range [i].ip_addr.iabuf,
-                         address_range [i].ip_addr.len,
-                         (unsigned char *)&address_range [i]);
-               address_range [i].refcnt = 1; /* XXX */
+               if (pool -> leases) {
+                       lease_reference (&lp -> next, pool -> leases, MDL);
+                       lease_dereference (&pool -> leases, MDL);
+               }
+               lease_reference (&pool -> leases, lp, MDL);
+               if (lp -> next)
+                       lease_reference (&lp -> next -> prev,
+                                        pool -> leases, MDL);
+               lease_hash_add (lease_ip_addr_hash, lp -> ip_addr.iabuf,
+                               lp -> ip_addr.len, lp, MDL);
+       }
+
+#if defined (COMPACT_LEASES)
+       /* Fill in the last lease if it hasn't been already... */
+       if (!pool -> last_lease) {
+               lease_reference (&pool -> last_lease, &address_range [0], MDL);
        }
+#endif
 
        /* Find out if any dangling leases are in range... */
        plp = (struct lease *)0;
@@ -639,45 +551,72 @@ void new_address_range (low, high, subnet, pool)
                   the list of dangling leases. */
                if (addr_eq (lnet, subnet -> net) &&
                    lhost >= i && lhost <= max) {
+                       struct lease *lt = (struct lease *)0;
                        if (plp) {
-                               plp -> next = lp -> next;
+                               if (plp -> next)
+                                       lease_dereference (&plp -> next, MDL);
+                               lease_reference (&plp -> next,
+                                                lp -> next, MDL);
                        } else {
-                               dangling_leases = lp -> next;
+                               lease_dereference (&dangling_leases, MDL);
+                               lease_reference (&dangling_leases,
+                                                lp -> next, MDL);
+                       }
+                       lease_dereference (&lp -> next, MDL);
+                       if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
+                               lt -> hostname = lp -> hostname;
+                               lp -> hostname = (char *)0;
+                               lt -> client_hostname = lp -> client_hostname;
+                               lp -> client_hostname = (char *)0;
+                               supersede_lease (lt, lp, 0, 0);
+                               lease_dereference (&lt, MDL);
                        }
-                       lp -> next = (struct lease *)0;
-                       address_range [lhost - i].hostname = lp -> hostname;
-                       address_range [lhost - i].client_hostname =
-                               lp -> client_hostname;
-                       supersede_lease (&address_range [lhost - i], lp, 0, 0);
-                       free_lease (lp, MDL);
+                       lease_dereference (&lp, MDL);
                } else
                        plp = lp;
        }
 }
 
-struct subnet *find_subnet (addr)
-       struct iaddr addr;
+/* There's really no way to free a lease, because of the aggregate way
+   we allocate them. */
+
+isc_result_t dhcp_lease_free (omapi_object_t *lease,
+                             const char *file, int line)
+{
+       return ISC_R_SUCCESS;
+}
+
+int find_subnet (struct subnet **sp,
+                struct iaddr addr, const char *file, int line)
 {
        struct subnet *rv;
 
        for (rv = subnets; rv; rv = rv -> next_subnet) {
-               if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
-                       return rv;
+               if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
+                       if (subnet_reference (sp, rv,
+                                             file, line) != ISC_R_SUCCESS)
+                               return 0;
+                       return 1;
+               }
        }
-       return (struct subnet *)0;
+       return 0;
 }
 
-struct subnet *find_grouped_subnet (share, addr)
-       struct shared_network *share;
-       struct iaddr addr;
+int find_grouped_subnet (struct subnet **sp,
+                        struct shared_network *share, struct iaddr addr,
+                        const char *file, int line)
 {
        struct subnet *rv;
 
        for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
-               if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net))
-                       return rv;
+               if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
+                       if (subnet_reference (sp, rv,
+                                             file, line) != ISC_R_SUCCESS)
+                               return 0;
+                       return 1;
+               }
        }
-       return (struct subnet *)0;
+       return 0;
 }
 
 int subnet_inner_than (subnet, scan, warnp)
@@ -722,10 +661,11 @@ void enter_subnet (subnet)
                   first. */
                if (subnet_inner_than (subnet, scan, 1)) {
                        if (prev) {
-                               prev -> next_subnet = subnet; 
+                               subnet_reference (&prev -> next_subnet,
+                                                 subnet, MDL);
                        } else
-                               subnets = subnet;
-                       subnet -> next_subnet = scan;
+                               subnet_reference (&subnets, subnet, MDL);
+                       subnet_reference (&subnet -> next_subnet, scan, MDL);
                        return;
                }
                prev = scan;
@@ -741,9 +681,12 @@ void enter_subnet (subnet)
 void enter_shared_network (share)
        struct shared_network *share;
 {
-       /* XXX Sort the nets into a balanced tree to make searching quicker. */
-       share -> next = shared_networks;
-       shared_networks = share;
+       if (shared_networks) {
+               shared_network_reference (&share -> next,
+                                         shared_networks, MDL);
+               shared_network_dereference (&shared_networks, MDL);
+       }
+       shared_network_reference (&shared_networks, share, MDL);
 }
        
 void new_shared_network_interface (cfile, share, name)
@@ -752,6 +695,7 @@ void new_shared_network_interface (cfile, share, name)
        const char *name;
 {
        struct interface_info *ip;
+       isc_result_t status;
 
        if (share -> interface) {
                parse_warn (cfile, 
@@ -764,20 +708,24 @@ void new_shared_network_interface (cfile, share, name)
                if (!strcmp (ip -> name, name))
                        break;
        if (!ip) {
-               ip = dmalloc (sizeof *ip, MDL);
-               if (!ip)
-                       log_fatal ("No memory to record interface %s", name);
-               memset (ip, 0, sizeof *ip);
+               status = interface_allocate (&ip, MDL);
+               if (status != ISC_R_SUCCESS)
+                       log_fatal ("new_shared_network_interface %s: %s",
+                                  name, isc_result_totext (status));
                if (strlen (name) > sizeof ip -> name) {
                        memcpy (ip -> name, name, (sizeof ip -> name) - 1);
                        ip -> name [(sizeof ip -> name) - 1] = 0;
                } else
                        strcpy (ip -> name, name);
-               ip -> next = interfaces;
+               if (interfaces) {
+                       interface_reference (&ip -> next, interfaces, MDL);
+                       interface_dereference (&interfaces, MDL);
+               }
+               interface_reference (&interfaces, ip, MDL);
                ip -> flags = INTERFACE_REQUESTED;
-               interfaces = ip;
-               ip -> shared_network = share;
-               share -> interface = ip;
+               /* XXX this is a reference loop. */
+               shared_network_reference (&ip -> shared_network, share, MDL);
+               interface_reference (&share -> interface, ip, MDL);
        }
 }
 
@@ -790,25 +738,20 @@ void new_shared_network_interface (cfile, share, name)
 void enter_lease (lease)
        struct lease *lease;
 {
-       struct lease *comp = find_lease_by_ip_addr (lease -> ip_addr);
+       struct lease *comp = (struct lease *)0;
+       isc_result_t status;
 
        /* If we don't have a place for this lease yet, save it for
           later. */
-       if (!comp) {
-               comp = new_lease (MDL);
-               if (!comp) {
-                       log_fatal ("No memory for lease %s\n",
-                              piaddr (lease -> ip_addr));
-               }
-               memset (comp, 0, sizeof *comp);
-               *comp = *lease;
-               comp -> next = dangling_leases;
-               comp -> prev = (struct lease *)0;
-               dangling_leases = comp;
+       if (!find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
+               if (comp -> next)
+                       lease_dereference (&comp -> next, MDL);
+               if (dangling_leases)
+                       lease_reference (&comp -> next, dangling_leases, MDL);
+               lease_reference (&dangling_leases, comp, MDL);
+               if (comp -> prev)
+                       lease_dereference (&comp -> prev, MDL);
        } else {
-               /* Record the hostname information in the lease. */
-               comp -> hostname = lease -> hostname;
-               comp -> client_hostname = lease -> client_hostname;
                supersede_lease (comp, lease, 0, 0);
        }
 }
@@ -884,7 +827,7 @@ int supersede_lease (comp, lease, commit, propogate)
        /* If the lease has been billed to a class, remove the billing. */
        if (comp -> billing_class &&
            comp -> billing_class != lease -> billing_class)
-               unbill_class (comp, comp -> billing_class);
+               unbill_class (comp, comp -> billing_class);
 
        /* Copy the data files, but not the linkages. */
        comp -> starts = lease -> starts;
@@ -907,7 +850,9 @@ int supersede_lease (comp, lease, commit, propogate)
                comp -> uid_max = 0;
        }
        comp -> uid_len = lease -> uid_len;
-       comp -> host = lease -> host;
+       if (comp -> host)
+               host_dereference (&comp -> host, MDL);
+       host_reference (&comp -> host, lease -> host, MDL);
        comp -> hardware_addr = lease -> hardware_addr;
        comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
                         (comp -> flags & ~EPHEMERAL_FLAGS));
@@ -916,6 +861,16 @@ int supersede_lease (comp, lease, commit, propogate)
        comp -> scope.bindings = lease -> scope.bindings;
        lease -> scope.bindings = (struct binding *)0;
 
+       /* Record the hostname information in the lease. */
+       if (comp -> hostname)
+               dfree (comp -> hostname, MDL);
+       comp -> hostname = lease -> hostname;
+       lease -> hostname = (char *)0;
+       if (comp -> client_hostname)
+               dfree (comp -> client_hostname, MDL);
+       comp -> client_hostname = lease -> client_hostname;
+       lease -> client_hostname = (char *)0;
+
        if (lease -> on_expiry) {
                if (comp -> on_expiry)
                        executable_statement_dereference (&comp -> on_expiry,
@@ -953,16 +908,37 @@ int supersede_lease (comp, lease, commit, propogate)
        /* Remove the lease from its current place in the 
           timeout sequence. */
        if (comp -> prev) {
-               comp -> prev -> next = comp -> next;
+               lease_dereference (&comp -> prev -> next, MDL);
+               if (comp -> next) {
+                       lease_reference (&comp -> prev -> next,
+                                        comp -> next, MDL);
+                       lease_dereference (&comp -> next, MDL);
+               }
        } else {
-               comp -> pool -> leases = comp -> next;
+               lease_dereference (&comp -> pool -> leases, MDL);
+               if (comp -> next) {
+                       lease_reference (&comp -> pool -> leases,
+                                        comp -> next, MDL);
+               }
        }
        if (comp -> next) {
-               comp -> next -> prev = comp -> prev;
+               lease_dereference (&comp -> next -> prev, MDL);
+               if (comp -> prev) {
+                       lease_reference (&comp -> next -> prev,
+                                        comp -> prev, MDL);
+               }
        }
        if (comp -> pool -> last_lease == comp) {
-               comp -> pool -> last_lease = comp -> prev;
+               lease_dereference (&comp -> pool -> last_lease, MDL);
+               if (comp -> prev)
+                       lease_reference (&comp -> pool -> last_lease,
+                                        comp -> prev, MDL);
        }
+       if (comp -> prev)
+               lease_dereference (&comp -> prev, MDL);
+       if (comp -> next)
+               lease_dereference (&comp -> next, MDL);
+
 
        /* If there's an expiry event on this lease, get rid of it
           (we may wind up putting it back, but we can't count on
@@ -980,12 +956,16 @@ int supersede_lease (comp, lease, commit, propogate)
                    && lp -> on_expiry
 #endif
                        ) {
-                       comp -> pool -> next_expiry = lp;
+                       lease_dereference (&comp -> pool -> next_expiry, MDL);
+                       lease_reference (&comp -> pool -> next_expiry,
+                                        lp, MDL);
                        if (commit)
                                add_timeout (lp -> ends,
-                                            pool_timer, lp -> pool);
+                                            pool_timer, lp -> pool,
+                                            (tvref_t)pool_reference,
+                                            (tvunref_t)pool_dereference);
                } else {
-                       comp -> pool -> next_expiry = (struct lease *)0;
+                       lease_dereference (&comp -> pool -> next_expiry, MDL);
                        if (commit)
                                cancel_timeout (pool_timer, comp -> pool);
                }
@@ -1002,8 +982,12 @@ int supersede_lease (comp, lease, commit, propogate)
        if (!lp) {
                /* Nothing on the list yet?    Just make comp the
                   head of the list. */
-               comp -> pool -> leases = comp;
-               comp -> pool -> last_lease = comp;
+               lease_reference (&comp -> pool -> leases, comp, MDL);
+               if (comp -> pool -> last_lease) {
+                       lease_dereference (&comp -> pool -> last_lease, MDL);
+                       lease_reference (&comp -> pool -> last_lease,
+                                        comp, MDL);
+               }
        } else if (lp -> ends > lease -> ends) {
                /* Skip down the list until we run out of list
                   or find a place for comp. */
@@ -1012,19 +996,32 @@ int supersede_lease (comp, lease, commit, propogate)
                }
                if (lp -> ends > lease -> ends) {
                        /* If we ran out of list, put comp at the end. */
-                       lp -> next = comp;
-                       comp -> prev = lp;
-                       comp -> next = (struct lease *)0;
-                       comp -> pool -> last_lease = comp;
+                       lease_reference (&lp -> next, comp, MDL);
+                       lease_reference (&comp -> prev, lp, MDL);
+                       if (comp -> pool -> last_lease)
+                               lease_dereference (&comp -> pool -> last_lease,
+                                                  MDL);
+                       lease_reference (&comp -> pool -> last_lease,
+                                        comp, MDL);
                } else {
                        /* If we didn't, put it between lp and
                           the previous item on the list. */
-                       if ((comp -> prev = lp -> prev))
-                               comp -> prev -> next = comp;
-                       else
-                               comp -> pool -> leases = comp;
-                       comp -> next = lp;
-                       lp -> prev = comp;
+                       if (lp -> prev) {
+                               lease_reference (&comp -> prev,
+                                                lp -> prev, MDL);
+                               lease_dereference (&lp -> prev -> next, MDL);
+                               lease_reference (&comp -> prev -> next,
+                                                comp, MDL);
+                               lease_dereference (&lp -> prev, MDL);
+                       } else {
+                               if (comp -> pool -> leases)
+                                       lease_dereference
+                                               (&comp -> pool -> leases, MDL);
+                               lease_reference (&comp -> pool -> leases,
+                                                comp, MDL);
+                       }
+                       lease_reference (&comp -> next, lp, MDL);
+                       lease_reference (&lp -> prev, comp, MDL);
                }
        } else {
                /* Skip up the list until we run out of list
@@ -1034,22 +1031,39 @@ int supersede_lease (comp, lease, commit, propogate)
                }
                if (lp -> ends < lease -> ends) {
                        /* If we ran out of list, put comp at the beginning. */
-                       lp -> prev = comp;
-                       comp -> next = lp;
-                       comp -> prev = (struct lease *)0;
-                       comp -> pool -> leases = comp;
+                       lease_reference (&lp -> prev, comp, MDL);
+                       lease_reference (&comp -> next, lp, MDL);
+                       if (comp -> pool -> leases)
+                               lease_dereference (&comp -> pool -> leases,
+                                                  MDL);
+                       lease_reference (&comp -> pool -> leases, comp, MDL);
                } else {
                        /* If we didn't, put it between lp and
                           the next item on the list. */
-                       if ((comp -> next = lp -> next))
-                               comp -> next -> prev = comp;
-                       else
-                               comp -> pool -> last_lease = comp;
-                       comp -> prev = lp;
-                       lp -> next = comp;
+                       if (lp -> next) {
+                               lease_reference (&comp -> next,
+                                                lp -> next, MDL);
+                               lease_dereference (&lp -> next -> prev, MDL);
+                               lease_reference (&lp -> next -> prev,
+                                                comp, MDL);
+                               lease_dereference (&lp -> next, MDL);
+                       } else {
+                               /* XXX are we really supposed to
+                                  XXX be doing this? */
+                               if (comp -> pool -> last_lease)
+                                       lease_dereference
+                                               (&comp -> pool -> last_lease,
+                                                MDL);
+                               lease_reference (&comp -> pool -> last_lease,
+                                                comp, MDL);
+                       }
+                       lease_reference (&comp -> prev, lp, MDL);
+                       lease_reference (&lp -> next, comp, MDL);
                }
        }
-       comp -> pool -> insertion_point = comp;
+       if (comp -> pool -> insertion_point)
+               lease_dereference (&comp -> pool -> insertion_point, MDL);
+       lease_reference (&comp -> pool -> insertion_point, comp, MDL);
 #if defined (FAILOVER_PROTOCOL)
        if (comp -> ends <= cur_time && lease -> ends > cur_time) {
                if (lease -> flags & PEER_IS_OWNER)
@@ -1105,11 +1119,20 @@ int supersede_lease (comp, lease, commit, propogate)
                            if (!comp -> pool -> next_expiry ||
                                (comp -> ends <
                                 comp -> pool -> next_expiry -> ends)) {
-                                   comp -> pool -> next_expiry = comp;
+                                   if (comp -> pool -> next_expiry)
+                                       lease_dereference
+                                               (&comp -> pool -> next_expiry,
+                                                MDL);
+                                   lease_reference
+                                           (&comp -> pool -> next_expiry,
+                                            comp, MDL);
                                    if (commit)
-                                           add_timeout (comp -> ends,
-                                                        pool_timer,
-                                                        comp -> pool);
+                                       add_timeout (comp -> ends,
+                                                    pool_timer,
+                                                    comp -> pool,
+                                                    (tvref_t)pool_reference,
+                                                    (tvunref_t)
+                                                    pool_dereference);
                             } else if (comp -> ends ==
                                        comp -> pool -> next_expiry -> ends) {
                                     /* If there are other leases that expire at
@@ -1128,7 +1151,12 @@ int supersede_lease (comp, lease, commit, propogate)
 #endif
                                                     install = foo;
                                     }
-                                    comp -> pool -> next_expiry = install;
+                                   lease_dereference
+                                           (&comp -> pool -> next_expiry,
+                                            MDL);
+                                    lease_reference
+                                           (&comp -> pool -> next_expiry,
+                                            install, MDL);
                             }
                        }
                }
@@ -1145,13 +1173,86 @@ int supersede_lease (comp, lease, commit, propogate)
                ;
 }
 
-/* Release the specified lease and re-hash it as appropriate. */
+/* Copy the contents of one lease into another, correctly maintaining
+   reference counts. */
+int lease_copy (struct lease **lp,
+               struct lease *lease, const char *file, int line)
+{
+       struct lease *lt = (struct lease *)0;
+       isc_result_t status;
 
+       status = lease_allocate (&lt, MDL);
+       if (status != ISC_R_SUCCESS)
+               return 0;
+
+       lt -> ip_addr = lease -> ip_addr;
+       lt -> starts = lease -> starts;
+       lt -> ends = lease -> ends;
+       lt -> timestamp = lease -> timestamp;
+       lt -> uid_len = lease -> uid_len;
+       lt -> uid_max = lease -> uid_max;
+       if (lease -> uid == lease -> uid_buf) {
+               lt -> uid = lt -> uid_buf;
+               memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
+       } else {
+               lt -> uid = dmalloc (lt -> uid_max, MDL);
+               if (!lt -> uid) {
+                       lease_dereference (&lt, MDL);
+                       return 0;
+               }
+               memcpy (lt -> uid, lease -> uid, lease -> uid_max);
+       }
+       if (lease -> hostname) {
+               lt -> hostname = dmalloc (strlen (lease -> hostname) + 1, MDL);
+               if (!lt -> hostname) {
+                       lease_dereference (&lt, MDL);
+                       return 0;
+               }
+               strcpy (lt -> hostname, lease -> hostname);
+       }
+       if (lease -> client_hostname) {
+               lt -> client_hostname =
+                       dmalloc (strlen (lease -> client_hostname) + 1, MDL);
+               if (!lt -> client_hostname) {
+                       lease_dereference (&lt, MDL);
+                       return 0;
+               }
+               strcpy (lt -> client_hostname, lease -> client_hostname);
+       }
+       lt -> scope = lease -> scope;
+       host_reference (&lt -> host, lease -> host, file, line);
+       subnet_reference (&lt -> subnet, lease -> subnet, file, line);
+       pool_reference (&lt -> pool, lease -> pool, file, line);
+       class_reference (&lt -> billing_class,
+                        lease -> billing_class, file, line);
+       lt -> hardware_addr = lease -> hardware_addr;
+       if (lease -> on_expiry)
+               executable_statement_reference (&lt -> on_expiry,
+                                               lease -> on_expiry,
+                                               file, line);
+       if (lease -> on_commit)
+               executable_statement_reference (&lt -> on_commit,
+                                               lease -> on_commit,
+                                               file, line);
+       if (lease -> on_release)
+               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;
+       status = lease_reference (lp, lt, file, line);
+       lease_dereference (&lt, MDL);
+       return status == ISC_R_SUCCESS;
+}
+
+/* Release the specified lease and re-hash it as appropriate. */
 void release_lease (lease, packet)
        struct lease *lease;
        struct packet *packet;
 {
-       struct lease lt;
+       struct lease *lt;
 
        /* If there are statements to execute when the lease is
           released, execute them. */
@@ -1171,20 +1272,21 @@ void release_lease (lease, packet)
                executable_statement_dereference (&lease -> on_expiry, MDL);
 
        if (lease -> ends > cur_time) {
-               lt = *lease;
+               if (!lease_copy (&lt, lease, MDL))
+                       return;
 
-               /* Events are reference-counted, so we can't just randomly
-                  make copies. */
-               lt.on_expiry = 0;
-               lt.on_release = 0;
-               lt.on_commit = 0;
+               if (lt -> on_commit)
+                       executable_statement_dereference (&lt -> on_commit,
+                                                         MDL);
 
                /* Blow away any bindings. */
-               lt.scope.bindings = (struct binding *)0;
+               lt -> scope.bindings = (struct binding *)0;
 
-               lt.ends = cur_time;
-               lt.billing_class = (struct class *)0;
-               supersede_lease (lease, &lt, 1, 1);
+               lt -> ends = cur_time;
+               if (lt -> billing_class)
+                       class_dereference (&lt -> billing_class, MDL);
+               supersede_lease (lease, lt, 1, 1);
+               lease_dereference (&lt, MDL);
        }
 }
 
@@ -1195,28 +1297,35 @@ void abandon_lease (lease, message)
        struct lease *lease;
        const char *message;
 {
-       struct lease lt;
+       struct lease *lt = (struct lease *)0;
 
        lease -> flags |= ABANDONED_LEASE;
-       lt = *lease;
+       if (!lease_copy (&lt, lease, MDL))
+               return;
 
-       /* Events are reference-counted, so we can't just randomly
-           make copies. */
-       lt.on_expiry = 0;
-       lt.on_release = 0;
-       lt.on_commit = 0;
+       if (lt -> on_expiry)
+               executable_statement_dereference (&lease -> on_expiry, MDL);
+       if (lt -> on_release)
+               executable_statement_dereference (&lease -> on_release, MDL);
+       if (lt -> on_commit)
+               executable_statement_dereference (&lease -> on_commit, MDL);
 
        /* Blow away any bindings. */
-       lt.scope.bindings = (struct binding *)0;
+       lt -> scope.bindings = (struct binding *)0;
 
-       lt.ends = cur_time; /* XXX */
+       lt -> ends = cur_time; /* XXX */
        log_error ("Abandoning IP address %s: %s",
              piaddr (lease -> ip_addr), message);
-       lt.hardware_addr.hlen = 0;
-       lt.uid = (unsigned char *)0;
-       lt.uid_len = 0;
-       lt.billing_class = (struct class *)0;
-       supersede_lease (lease, &lt, 1, 1);
+       lt -> hardware_addr.hlen = 0;
+       if (lt -> uid != lt -> uid_buf)
+               dfree (lt -> uid, MDL);
+       lt -> uid = (unsigned char *)0;
+       lt -> uid_len = 0;
+       lt -> uid_max = 0;
+       if (lt -> billing_class)
+               class_dereference (&lt -> billing_class, MDL);
+       supersede_lease (lease, lt, 1, 1);
+       lease_dereference (&lt, MDL);
 }
 
 /* Abandon the specified lease (set its timeout to infinity and its
@@ -1225,25 +1334,32 @@ void abandon_lease (lease, message)
 void dissociate_lease (lease)
        struct lease *lease;
 {
-       struct lease lt;
+       struct lease *lt = (struct lease *)0;
 
-       lt = *lease;
-       /* Events are reference-counted, so we can't just randomly
-           make copies. */
-       lt.on_expiry = 0;
-       lt.on_release = 0;
-       lt.on_commit = 0;
+       if (!lease_copy (&lt, lease, MDL))
+               return;
+
+       if (lt -> on_expiry)
+               executable_statement_dereference (&lease -> on_expiry, MDL);
+       if (lt -> on_release)
+               executable_statement_dereference (&lease -> on_release, MDL);
+       if (lt -> on_commit)
+               executable_statement_dereference (&lease -> on_commit, MDL);
 
        /* Blow away any bindings. */
-       lt.scope.bindings = (struct binding *)0;
-
-       if (lt.ends > cur_time)
-               lt.ends = cur_time;
-       lt.hardware_addr.hlen = 0;
-       lt.uid = (unsigned char *)0;
-       lt.uid_len = 0;
-       lt.billing_class = (struct class *)0;
-       supersede_lease (lease, &lt, 1, 1);
+       lt -> scope.bindings = (struct binding *)0;
+
+       lt -> ends = cur_time; /* XXX */
+       lt -> hardware_addr.hlen = 0;
+       if (lt -> uid != lt -> uid_buf)
+               dfree (lt -> uid, MDL);
+       lt -> uid = (unsigned char *)0;
+       lt -> uid_len = 0;
+       lt -> uid_max = 0;
+       if (lt -> billing_class)
+               class_dereference (&lt -> billing_class, MDL);
+       supersede_lease (lease, lt, 1, 1);
+       lease_dereference (&lt, MDL);
 }
 
 /* Timer called when a lease in a particular pool expires. */
@@ -1309,40 +1425,41 @@ void pool_timer (vpool)
                        pool -> local_leases++;
 #endif
        }
-       pool -> next_expiry = lease;
-       if (lease)
-               add_timeout (lease -> ends, pool_timer, pool);
+       if (pool -> next_expiry)
+               lease_dereference (&pool -> next_expiry, MDL);
+       if (lease) {
+               lease_reference (&pool -> next_expiry, lease, MDL);
+               add_timeout (lease -> ends, pool_timer, pool,
+                            (tvref_t)pool_reference,
+                            (tvunref_t)pool_dereference);
+       }
 }
 
 /* Locate the lease associated with a given IP address... */
 
-struct lease *find_lease_by_ip_addr (addr)
-       struct iaddr addr;
+int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
+                          const char *file, int line)
 {
-       struct lease *lease = (struct lease *)hash_lookup (lease_ip_addr_hash,
-                                                          addr.iabuf,
-                                                          addr.len);
-       return lease;
+       return lease_hash_lookup (lp, lease_ip_addr_hash,
+                                 addr.iabuf, addr.len, file, line);
 }
 
-struct lease *find_lease_by_uid (uid, len)
-       const unsigned char *uid;
-       unsigned len;
+int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
+                      unsigned len, const char *file, int line)
 {
-       struct lease *lease = (struct lease *)hash_lookup (lease_uid_hash,
-                                                          uid, len);
-       return lease;
+       if (len == 0)
+               return 0;
+       return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
 }
 
-struct lease *find_lease_by_hw_addr (hwaddr, hwlen)
-       const unsigned char *hwaddr;
-       unsigned hwlen;
+int find_lease_by_hw_addr (struct lease **lp,
+                          const unsigned char *hwaddr, unsigned hwlen,
+                          const char *file, int line)
 {
-       struct lease *lease;
-
-       lease = (struct lease *)hash_lookup (lease_hw_addr_hash,
-                                            hwaddr, hwlen);
-       return lease;
+       if (hwlen == 0)
+               return 0;
+       return lease_hash_lookup (lp, lease_hw_addr_hash,
+                                 hwaddr, hwlen, file, line);
 }
 
 /* Add the specified lease to the uid hash. */
@@ -1350,19 +1467,20 @@ struct lease *find_lease_by_hw_addr (hwaddr, hwlen)
 void uid_hash_add (lease)
        struct lease *lease;
 {
-       struct lease *head =
-               find_lease_by_uid (lease -> uid, lease -> uid_len);
+       struct lease *head = (struct lease *)0;
        struct lease *scan;
 
+
        /* If it's not in the hash, just add it. */
-       if (!head)
-               add_hash (lease_uid_hash, lease -> uid,
-                         lease -> uid_len, (unsigned char *)lease);
+       if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
+               lease_hash_add (lease_uid_hash, lease -> uid,
+                               lease -> uid_len, lease, MDL);
        else {
                /* Otherwise, attach it to the end of the list. */
                for (scan = head; scan -> n_uid; scan = scan -> n_uid)
                        ;
-               scan -> n_uid = lease;
+               lease_reference (&scan -> n_uid, lease, MDL);
+               lease_dereference (&head, MDL);
        }
 }
 
@@ -1371,13 +1489,13 @@ void uid_hash_add (lease)
 void uid_hash_delete (lease)
        struct lease *lease;
 {
-       struct lease *head =
-               find_lease_by_uid (lease -> uid, lease -> uid_len);
+       struct lease *head = (struct lease *)0;
        struct lease *scan;
 
        /* If it's not in the hash, we have no work to do. */
-       if (!head) {
-               lease -> n_uid = (struct lease *)0;
+       if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
+               if (lease -> n_uid)
+                       lease_dereference (&lease -> n_uid, MDL);
                return;
        }
 
@@ -1385,25 +1503,33 @@ void uid_hash_delete (lease)
           remove the hash table entry and add a new one with the
           next lease on the list (if there is one). */
        if (head == lease) {
-               delete_hash_entry (lease_uid_hash,
-                                  lease -> uid, lease -> uid_len);
-               if (lease -> n_uid)
-                       add_hash (lease_uid_hash,
-                                 lease -> n_uid -> uid,
-                                 lease -> n_uid -> uid_len,
-                                 (unsigned char *)(lease -> n_uid));
+               lease_hash_delete (lease_uid_hash,
+                                  lease -> uid, lease -> uid_len, MDL);
+               if (lease -> n_uid) {
+                       lease_hash_add (lease_uid_hash,
+                                       lease -> n_uid -> uid,
+                                       lease -> n_uid -> uid_len,
+                                       lease -> n_uid, MDL);
+                       lease_dereference (&lease -> n_uid, MDL);
+               }
        } else {
                /* Otherwise, look for the lease in the list of leases
                   attached to the hash table entry, and remove it if
                   we find it. */
                for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
                        if (scan -> n_uid == lease) {
-                               scan -> n_uid = scan -> n_uid -> n_uid;
+                               lease_dereference (&scan -> n_uid, MDL);
+                               if (lease -> n_uid) {
+                                       lease_reference (&scan -> n_uid,
+                                                        lease -> n_uid, MDL);
+                                       lease_dereference (&lease -> n_uid,
+                                                          MDL);
+                               }
                                break;
                        }
                }
+               lease_dereference (&head, MDL);
        }
-       lease -> n_uid = (struct lease *)0;
 }
 
 /* Add the specified lease to the hardware address hash. */
@@ -1411,22 +1537,22 @@ void uid_hash_delete (lease)
 void hw_hash_add (lease)
        struct lease *lease;
 {
-       struct lease *head =
-               find_lease_by_hw_addr (lease -> hardware_addr.hbuf,
-                                      lease -> hardware_addr.hlen);
+       struct lease *head = (struct lease *)0;
        struct lease *scan;
 
        /* If it's not in the hash, just add it. */
-       if (!head)
-               add_hash (lease_hw_addr_hash,
-                         lease -> hardware_addr.hbuf,
-                         lease -> hardware_addr.hlen,
-                         (unsigned char *)lease);
+       if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
+                                   lease -> hardware_addr.hlen, MDL))
+               lease_hash_add (lease_hw_addr_hash,
+                               lease -> hardware_addr.hbuf,
+                               lease -> hardware_addr.hlen,
+                               lease, MDL);
        else {
                /* Otherwise, attach it to the end of the list. */
                for (scan = head; scan -> n_hw; scan = scan -> n_hw)
                        ;
-               scan -> n_hw = lease;
+               lease_reference (&scan -> n_hw, lease, MDL);
+               lease_dereference (&head, MDL);
        }
 }
 
@@ -1435,14 +1561,14 @@ void hw_hash_add (lease)
 void hw_hash_delete (lease)
        struct lease *lease;
 {
-       struct lease *head =
-               find_lease_by_hw_addr (lease -> hardware_addr.hbuf,
-                                      lease -> hardware_addr.hlen);
+       struct lease *head = (struct lease *)0;
        struct lease *scan;
 
        /* If it's not in the hash, we have no work to do. */
-       if (!head) {
-               lease -> n_hw = (struct lease *)0;
+       if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
+                                   lease -> hardware_addr.hlen, MDL)) {
+               if (lease -> n_hw)
+                       lease_dereference (&lease -> n_hw, MDL);
                return;
        }
 
@@ -1450,26 +1576,34 @@ void hw_hash_delete (lease)
           remove the hash table entry and add a new one with the
           next lease on the list (if there is one). */
        if (head == lease) {
-               delete_hash_entry (lease_hw_addr_hash,
+               lease_hash_delete (lease_hw_addr_hash,
                                   lease -> hardware_addr.hbuf,
-                                  lease -> hardware_addr.hlen);
-               if (lease -> n_hw)
-                       add_hash (lease_hw_addr_hash,
-                                 lease -> n_hw -> hardware_addr.hbuf,
-                                 lease -> n_hw -> hardware_addr.hlen,
-                                 (unsigned char *)(lease -> n_hw));
+                                  lease -> hardware_addr.hlen, MDL);
+               if (lease -> n_hw) {
+                       lease_hash_add (lease_hw_addr_hash,
+                                       lease -> n_hw -> hardware_addr.hbuf,
+                                       lease -> n_hw -> hardware_addr.hlen,
+                                       lease -> n_hw, MDL);
+                       lease_dereference (&lease -> n_hw, MDL);
+               }
        } else {
                /* Otherwise, look for the lease in the list of leases
                   attached to the hash table entry, and remove it if
                   we find it. */
                for (scan = head; scan -> n_hw; scan = scan -> n_hw) {
                        if (scan -> n_hw == lease) {
-                               scan -> n_hw = scan -> n_hw -> n_hw;
+                               lease_dereference (&scan -> n_hw, MDL);
+                               if (lease -> n_hw) {
+                                       lease_reference (&scan -> n_hw,
+                                                        lease -> n_hw, MDL);
+                                       lease_dereference (&lease -> n_hw,
+                                                          MDL);
+                               }
                                break;
                        }
                }
        }
-       lease -> n_hw = (struct lease *)0;
+       lease_dereference (&head, MDL);
 }
 
 /* Write all interesting leases to permanent storage. */
@@ -1633,3 +1767,7 @@ void dump_subnets ()
                }
        }
 }
+
+HASH_FUNCTIONS (lease, const unsigned char *, struct lease)
+HASH_FUNCTIONS (host, const unsigned char *, struct host_decl)
+HASH_FUNCTIONS (class, const char *, struct class)
index fdb788263d864cc3259e018c00e89ee535f32b12..9938668b3729e5ff389db7295016ac245840c5a5 100644 (file)
 
 #ifndef lint
 static char copyright[] =
-"$Id: omapi.c,v 1.27 2000/03/17 04:00:32 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: omapi.c,v 1.28 2000/05/16 23:03:48 mellon Exp $ Copyright (c) 1999-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
 #include <omapip/omapip_p.h>
 
 omapi_object_type_t *dhcp_type_lease;
-omapi_object_type_t *dhcp_type_group;
 omapi_object_type_t *dhcp_type_pool;
-omapi_object_type_t *dhcp_type_shared_network;
-omapi_object_type_t *dhcp_type_subnet;
 omapi_object_type_t *dhcp_type_class;
 #if defined (FAILOVER_PROTOCOL)
 omapi_object_type_t *dhcp_type_failover_state;
@@ -81,37 +78,26 @@ void dhcp_db_objects_setup ()
                                             dhcp_lease_stuff_values,
                                             dhcp_lease_lookup, 
                                             dhcp_lease_create,
-                                            dhcp_lease_remove);
+                                            dhcp_lease_remove,
+                                            dhcp_lease_free, 0,
+                                            sizeof (struct lease));
        if (status != ISC_R_SUCCESS)
                log_fatal ("Can't register lease object type: %s",
                           isc_result_totext (status));
 
-       status = omapi_object_type_register (&dhcp_type_group,
-                                            "group",
-                                            dhcp_group_set_value,
-                                            dhcp_group_get_value,
-                                            dhcp_group_destroy,
-                                            dhcp_group_signal_handler,
-                                            dhcp_group_stuff_values,
-                                            dhcp_group_lookup, 
-                                            dhcp_group_create,
-                                            dhcp_group_remove);
+       status = omapi_object_type_register (&dhcp_type_class,
+                                            "class",
+                                            dhcp_class_set_value,
+                                            dhcp_class_get_value,
+                                            dhcp_class_destroy,
+                                            dhcp_class_signal_handler,
+                                            dhcp_class_stuff_values,
+                                            dhcp_class_lookup, 
+                                            dhcp_class_create,
+                                            dhcp_class_remove, 0, 0,
+                                            sizeof (struct class));
        if (status != ISC_R_SUCCESS)
-               log_fatal ("Can't register group object type: %s",
-                          isc_result_totext (status));
-
-       status = omapi_object_type_register (&dhcp_type_host,
-                                            "host",
-                                            dhcp_host_set_value,
-                                            dhcp_host_get_value,
-                                            dhcp_host_destroy,
-                                            dhcp_host_signal_handler,
-                                            dhcp_host_stuff_values,
-                                            dhcp_host_lookup, 
-                                            dhcp_host_create,
-                                            dhcp_host_remove);
-       if (status != ISC_R_SUCCESS)
-               log_fatal ("Can't register host object type: %s",
+               log_fatal ("Can't register class object type: %s",
                           isc_result_totext (status));
 
        status = omapi_object_type_register (&dhcp_type_pool,
@@ -123,7 +109,8 @@ void dhcp_db_objects_setup ()
                                             dhcp_pool_stuff_values,
                                             dhcp_pool_lookup, 
                                             dhcp_pool_create,
-                                            dhcp_pool_remove);
+                                            dhcp_pool_remove, 0, 0,
+                                            sizeof (struct pool));
 
        if (status != ISC_R_SUCCESS)
                log_fatal ("Can't register pool object type: %s",
@@ -139,7 +126,9 @@ void dhcp_db_objects_setup ()
                                             dhcp_failover_state_stuff,
                                             dhcp_failover_state_lookup, 
                                             dhcp_failover_state_create,
-                                            dhcp_failover_state_remove);
+                                            dhcp_failover_state_remove,
+                                            0, 0,
+                                            sizeof (dhcp_failover_state_t));
 
        if (status != ISC_R_SUCCESS)
                log_fatal ("Can't register failover state object type: %s",
@@ -152,7 +141,8 @@ void dhcp_db_objects_setup ()
                                             dhcp_failover_link_destroy,
                                             dhcp_failover_link_signal,
                                             dhcp_failover_link_stuff_values,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof (dhcp_failover_link_t));
 
        if (status != ISC_R_SUCCESS)
                log_fatal ("Can't register failover link object type: %s",
@@ -165,7 +155,9 @@ void dhcp_db_objects_setup ()
                                             dhcp_failover_listener_destroy,
                                             dhcp_failover_listener_signal,
                                             dhcp_failover_listener_stuff,
-                                            0, 0, 0);
+                                            0, 0, 0, 0, 0,
+                                            sizeof
+                                            (dhcp_failover_listener_t));
 
        if (status != ISC_R_SUCCESS)
                log_fatal ("Can't register failover listener object type: %s",
@@ -311,9 +303,8 @@ isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
        uid_hash_delete (lease);
        hw_hash_delete (lease);
        if (lease -> billing_class)
-               omapi_object_dereference
-                       ((omapi_object_t **)&lease -> billing_class,
-                        file, line);
+               class_dereference
+                       (&lease -> billing_class, file, line);
        if (lease -> uid && lease -> uid != &lease -> uid_buf [0]) {
                dfree (lease -> uid, MDL);
                lease -> uid = &lease -> uid_buf [0];
@@ -328,14 +319,11 @@ isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
                lease -> hostname = (char *)0;
        }
        if (lease -> host)
-               omapi_object_dereference ((omapi_object_t **)&lease -> host,
-                                         file, line);
+               host_dereference (&lease -> host, file, line);
        if (lease -> subnet)
-               omapi_object_dereference ((omapi_object_t **)&lease -> subnet,
-                                         file, line);
+               subnet_dereference (&lease -> subnet, file, line);
        if (lease -> pool)
-               omapi_object_dereference ((omapi_object_t **)&lease -> pool,
-                                         file, line);
+               pool_dereference (&lease -> pool, file, line);
        if (lease -> on_expiry)
                executable_statement_dereference (&lease -> on_expiry,
                                                  file, line);
@@ -372,7 +360,11 @@ isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
                if (lease -> hardware_addr.hlen == 0 ||
                    lease -> hardware_addr.hlen > 17)
                        return ISC_R_INVALIDARG;
-               if (!write_lease (lease) || !commit_leases ()) {
+               if (!write_lease (lease) || !commit_leases ()
+#if defined (FAILOVER_PROTOCOL)
+                   || !dhcp_failover_queue_update (lease)
+#endif
+                       ) {
                        return ISC_R_IOERROR;
                }
                updatep = 1;
@@ -582,10 +574,10 @@ isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
        /* Now look for an IP address. */
        status = omapi_get_value_str (ref, id, "ip-address", &tv);
        if (status == ISC_R_SUCCESS) {
-               lease = ((struct lease *)
-                        hash_lookup (lease_ip_addr_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               lease = (struct lease *)0;
+               lease_hash_lookup (&lease, lease_ip_addr_hash,
+                                  tv -> value -> u.buffer.value,
+                                  tv -> value -> u.buffer.len, MDL);
 
                omapi_value_dereference (&tv, MDL);
 
@@ -593,29 +585,33 @@ isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
                   then the query was invalid. */
                if (*lp && *lp != (omapi_object_t *)lease) {
                        omapi_object_dereference (lp, MDL);
+                       lease_dereference (&lease, MDL);
                        return ISC_R_KEYCONFLICT;
                } else if (!lease) {
                        if (*lp)
                                omapi_object_dereference (lp, MDL);
                        return ISC_R_NOTFOUND;
-               } else if (!*lp)
+               } else if (!*lp) {
                        /* XXX fix so that hash lookup itself creates
                           XXX the reference. */
                        omapi_object_reference (lp,
                                                (omapi_object_t *)lease, MDL);
+                       lease_dereference (&lease, MDL);
+               }
        }
 
        /* Now look for a client identifier. */
        status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
        if (status == ISC_R_SUCCESS) {
-               lease = ((struct lease *)
-                        hash_lookup (lease_uid_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               lease = (struct lease *)0;
+               lease_hash_lookup (&lease, lease_uid_hash,
+                                  tv -> value -> u.buffer.value,
+                                  tv -> value -> u.buffer.len, MDL);
                omapi_value_dereference (&tv, MDL);
                        
                if (*lp && *lp != (omapi_object_t *)lease) {
                        omapi_object_dereference (lp, MDL);
+                       lease_dereference (&lease, MDL);
                        return ISC_R_KEYCONFLICT;
                } else if (!lease) {
                        if (*lp)
@@ -630,20 +626,22 @@ isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
                           XXX the reference. */
                        omapi_object_reference (lp,
                                                (omapi_object_t *)lease, MDL);
+                       lease_dereference (&lease, MDL);
                }
        }
 
        /* Now look for a hardware address. */
        status = omapi_get_value_str (ref, id, "hardware-address", &tv);
        if (status == ISC_R_SUCCESS) {
-               lease = ((struct lease *)
-                        hash_lookup (lease_hw_addr_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               lease = (struct lease *)0;
+               lease_hash_lookup (&lease, lease_hw_addr_hash,
+                                  tv -> value -> u.buffer.value,
+                                  tv -> value -> u.buffer.len, MDL);
                omapi_value_dereference (&tv, MDL);
                        
                if (*lp && *lp != (omapi_object_t *)lease) {
                        omapi_object_dereference (lp, MDL);
+                       lease_dereference (&lease, MDL);
                        return ISC_R_KEYCONFLICT;
                } else if (!lease) {
                        if (*lp)
@@ -652,12 +650,14 @@ isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
                } else if (lease -> n_hw) {
                        if (*lp)
                            omapi_object_dereference (lp, MDL);
+                       lease_dereference (&lease, MDL);
                        return ISC_R_MULTIPLE;
                } else if (!*lp) {
                        /* XXX fix so that hash lookup itself creates
                           XXX the reference. */
                        omapi_object_reference (lp,
                                                (omapi_object_t *)lease, MDL);
+                       lease_dereference (&lease, MDL);
                }
        }
 
@@ -680,317 +680,6 @@ isc_result_t dhcp_lease_remove (omapi_object_t *lp,
        return ISC_R_NOTIMPLEMENTED;
 }
 
-isc_result_t dhcp_group_set_value  (omapi_object_t *h,
-                                   omapi_object_t *id,
-                                   omapi_data_string_t *name,
-                                   omapi_typed_data_t *value)
-{
-       struct group_object *group;
-       isc_result_t status;
-       int foo;
-
-       if (h -> type != dhcp_type_group)
-               return ISC_R_INVALIDARG;
-       group = (struct group_object *)h;
-
-       /* XXX For now, we can only set these values on new group objects. 
-          XXX Soon, we need to be able to update group objects. */
-       if (!omapi_ds_strcmp (name, "name")) {
-               if (group -> name)
-                       return ISC_R_EXISTS;
-               if (value -> type == omapi_datatype_data ||
-                   value -> type == omapi_datatype_string) {
-                       group -> name = dmalloc (value -> u.buffer.len + 1,
-                                                MDL);
-                       if (!group -> name)
-                               return ISC_R_NOMEMORY;
-                       memcpy (group -> name,
-                               value -> u.buffer.value,
-                               value -> u.buffer.len);
-                       group -> name [value -> u.buffer.len] = 0;
-               } else
-                       return ISC_R_INVALIDARG;
-               return ISC_R_SUCCESS;
-       }
-
-       if (!omapi_ds_strcmp (name, "statements")) {
-               if (group -> group && group -> group -> statements)
-                       return ISC_R_EXISTS;
-               if (!group -> group)
-                       group -> group = clone_group (&root_group, MDL);
-               if (!group -> group)
-                       return ISC_R_NOMEMORY;
-               if (value -> type == omapi_datatype_data ||
-                   value -> type == omapi_datatype_string) {
-                       struct parse *parse;
-                       int lose = 0;
-                       parse = (struct parse *)0;
-                       status = new_parse (&parse, -1,
-                                           (char *)value -> u.buffer.value,
-                                           value -> u.buffer.len,
-                                           "network client");
-                       if (status != ISC_R_SUCCESS)
-                               return status;
-                       if (!(parse_executable_statements
-                             (&group -> group -> statements, parse, &lose,
-                              context_any))) {
-                               end_parse (&parse);
-                               return ISC_R_BADPARSE;
-                       }
-                       end_parse (&parse);
-                       return ISC_R_SUCCESS;
-               } else
-                       return ISC_R_INVALIDARG;
-       }
-
-       /* Try to find some inner object that can take the value. */
-       if (h -> inner && h -> inner -> type -> set_value) {
-               status = ((*(h -> inner -> type -> set_value))
-                         (h -> inner, id, name, value));
-               if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
-                       return status;
-       }
-                         
-       return ISC_R_NOTFOUND;
-}
-
-
-isc_result_t dhcp_group_get_value (omapi_object_t *h, omapi_object_t *id,
-                                  omapi_data_string_t *name,
-                                  omapi_value_t **value)
-{
-       struct group_object *group;
-       isc_result_t status;
-       struct data_string ip_addrs;
-
-       if (h -> type != dhcp_type_group)
-               return ISC_R_INVALIDARG;
-       group = (struct group_object *)h;
-
-       if (!omapi_ds_strcmp (name, "name"))
-               return omapi_make_string_value (value,
-                                               name, group -> name, MDL);
-
-       /* Try to find some inner object that can take the value. */
-       if (h -> inner && h -> inner -> type -> get_value) {
-               status = ((*(h -> inner -> type -> get_value))
-                         (h -> inner, id, name, value));
-               if (status == ISC_R_SUCCESS)
-                       return status;
-       }
-       return ISC_R_NOTFOUND;
-}
-
-isc_result_t dhcp_group_destroy (omapi_object_t *h, const char *file, int line)
-{
-       struct group_object *group, *t;
-       isc_result_t status;
-
-       if (h -> type != dhcp_type_group)
-               return ISC_R_INVALIDARG;
-       group = (struct group_object *)h;
-
-       if (group -> name) {
-               if (group_name_hash) {
-                       t = ((struct group_object *)
-                            hash_lookup (group_name_hash,
-                                         (unsigned char *)group -> name,
-                                         strlen (group -> name)));
-                       if (t) {
-                               delete_hash_entry (group_name_hash,
-                                                  (unsigned char *)
-                                                  group -> name,
-                                                  strlen (group -> name));
-                               --group -> refcnt;
-                       }
-               }
-               dfree (group -> name, file, line);
-               group -> name = (char *)0;
-       }
-       if (group -> group)
-               group -> group = (struct group *)0; /* XXX refcounts!!! */
-
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t dhcp_group_signal_handler (omapi_object_t *h,
-                                       const char *name, va_list ap)
-{
-       struct group_object *group, *t;
-       isc_result_t status;
-       int updatep = 0;
-
-       if (h -> type != dhcp_type_group)
-               return ISC_R_INVALIDARG;
-       group = (struct group_object *)h;
-
-       if (!strcmp (name, "updated")) {
-               /* A group object isn't valid if a subgroup hasn't yet been
-                  associated with it. */
-               if (!group -> group)
-                       return ISC_R_INVALIDARG;
-
-               /* Group objects always have to have names. */
-               if (!group -> name) {
-                       char hnbuf [64];
-                       sprintf (hnbuf, "ng%08lx%08lx",
-                                cur_time, (unsigned long)group);
-                       group -> name = dmalloc (strlen (hnbuf) + 1, MDL);
-                       if (!group -> name)
-                               return ISC_R_NOMEMORY;
-                       strcpy (group -> name, hnbuf);
-               }
-
-               supersede_group (group, 1);
-               updatep = 1;
-       }
-
-       /* Try to find some inner object that can take the value. */
-       if (h -> inner && h -> inner -> type -> get_value) {
-               status = ((*(h -> inner -> type -> signal_handler))
-                         (h -> inner, name, ap));
-               if (status == ISC_R_SUCCESS)
-                       return status;
-       }
-       if (updatep)
-               return ISC_R_SUCCESS;
-       return ISC_R_NOTFOUND;
-}
-
-isc_result_t dhcp_group_stuff_values (omapi_object_t *c,
-                                     omapi_object_t *id,
-                                     omapi_object_t *h)
-{
-       struct group_object *group;
-       isc_result_t status;
-
-       if (h -> type != dhcp_type_group)
-               return ISC_R_INVALIDARG;
-       group = (struct group_object *)h;
-
-       /* Write out all the values. */
-       if (group -> name) {
-               status = omapi_connection_put_name (c, "name");
-               if (status != ISC_R_SUCCESS)
-                       return status;
-               status = omapi_connection_put_string (c, group -> name);
-               if (status != ISC_R_SUCCESS)
-                       return status;
-       }
-
-       /* Write out the inner object, if any. */
-       if (h -> inner && h -> inner -> type -> stuff_values) {
-               status = ((*(h -> inner -> type -> stuff_values))
-                         (c, id, h -> inner));
-               if (status == ISC_R_SUCCESS)
-                       return status;
-       }
-
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t dhcp_group_lookup (omapi_object_t **lp,
-                               omapi_object_t *id, omapi_object_t *ref)
-{
-       omapi_value_t *tv = (omapi_value_t *)0;
-       isc_result_t status;
-       struct group_object *group;
-
-       /* First see if we were sent a handle. */
-       status = omapi_get_value_str (ref, id, "handle", &tv);
-       if (status == ISC_R_SUCCESS) {
-               status = omapi_handle_td_lookup (lp, tv -> value);
-
-               omapi_value_dereference (&tv, MDL);
-               if (status != ISC_R_SUCCESS)
-                       return status;
-
-               /* Don't return the object if the type is wrong. */
-               if ((*lp) -> type != dhcp_type_group) {
-                       omapi_object_dereference (lp, MDL);
-                       return ISC_R_INVALIDARG;
-               }
-       }
-
-       /* Now look for a name. */
-       status = omapi_get_value_str (ref, id, "name", &tv);
-       if (status == ISC_R_SUCCESS) {
-               if (group_name_hash) {
-                       group = ((struct group_object *)
-                                hash_lookup (group_name_hash,
-                                             tv -> value -> u.buffer.value,
-                                             tv -> value -> u.buffer.len));
-                       omapi_value_dereference (&tv, MDL);
-
-                       /* Don't register a deleted group here. */
-                       if (group -> flags & GROUP_OBJECT_DELETED) {
-                               if (!*lp)
-                                       return ISC_R_NOTFOUND;
-                               group = (struct group_object *)0;
-                       }
-
-                       if (*lp && *lp != (omapi_object_t *)group) {
-                           omapi_object_dereference (lp, MDL);
-                           return ISC_R_KEYCONFLICT;
-                       } else if (!group) {
-                           omapi_object_dereference (lp, MDL);
-                           return ISC_R_NOTFOUND;
-                       } else if (!*lp) {
-                           /* XXX fix so that hash lookup itself creates
-                              XXX the reference. */
-                           omapi_object_reference (lp,
-                                                   (omapi_object_t *)group,
-                                                   MDL);
-                       }
-               } else if (!*lp)
-                       return ISC_R_NOTFOUND;
-       }
-
-       /* If we get to here without finding a group, no valid key was
-          specified. */
-       if (!*lp)
-               return ISC_R_NOKEYS;
-
-       if (((struct group_object *)(*lp)) -> flags & GROUP_OBJECT_DELETED) {
-               omapi_object_dereference (lp, MDL);
-               return ISC_R_NOTFOUND;
-       }
-       return ISC_R_SUCCESS;
-}
-
-isc_result_t dhcp_group_create (omapi_object_t **lp,
-                              omapi_object_t *id)
-{
-       struct group_object *group;
-       group = (struct group_object *)dmalloc (sizeof (struct group_object),
-                                               MDL);
-       if (!group)
-               return ISC_R_NOMEMORY;
-       memset (group, 0, sizeof *group);
-       group -> refcnt = 0;
-       group -> type = dhcp_type_group;
-       group -> flags = GROUP_OBJECT_DYNAMIC;
-       return omapi_object_reference (lp, (omapi_object_t *)group, MDL);
-}
-
-isc_result_t dhcp_group_remove (omapi_object_t *lp,
-                               omapi_object_t *id)
-{
-       struct group_object *group;
-       isc_result_t status;
-       if (lp -> type != dhcp_type_group)
-               return ISC_R_INVALIDARG;
-       group = (struct group_object *)lp;
-
-       group -> flags |= GROUP_OBJECT_DELETED;
-       if (!write_group (group) || !commit_leases ())
-               return ISC_R_IOERROR;
-
-       status = dhcp_group_destroy ((omapi_object_t *)group, MDL);
-
-       return ISC_R_SUCCESS;
-}
-
 isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                                   omapi_object_t *id,
                                   omapi_data_string_t *name,
@@ -1028,20 +717,19 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                if (value -> type == omapi_datatype_data ||
                    value -> type == omapi_datatype_string) {
                        struct group_object *group;
-                       group = ((struct group_object *)
-                                hash_lookup (group_name_hash,
-                                             value -> u.buffer.value,
-                                             value -> u.buffer.len));
+                       group = (struct group_object *)0;
+                       group_hash_lookup (&group, group_name_hash,
+                                          value -> u.buffer.value,
+                                          value -> u.buffer.len, MDL);
                        if (!group || (group -> flags & GROUP_OBJECT_DELETED))
                                return ISC_R_NOTFOUND;
-                       host -> group = group -> group;
+                       group_reference (&host -> group, group -> group, MDL);
                        if (host -> named_group)
-                               omapi_object_dereference
-                                       ((omapi_object_t **)
-                                        &host -> named_group, MDL);
-                       omapi_object_reference ((omapi_object_t **)
-                                               &host -> named_group,
-                                               (omapi_object_t *)group, MDL);
+                               group_object_dereference (&host -> named_group,
+                                                         MDL);
+                       group_object_reference (&host -> named_group,
+                                               group, MDL);
+                       group_object_dereference (&group, MDL);
                } else
                        return ISC_R_INVALIDARG;
                return ISC_R_SUCCESS;
@@ -1126,15 +814,17 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
        }
 
        if (!omapi_ds_strcmp (name, "statements")) {
-               if (!host -> group)
-                       host -> group = clone_group (&root_group, MDL);
-               else {
+               if (!host -> group) {
+                       if (!clone_group (&host -> group, root_group, MDL))
+                               return ISC_R_NOMEMORY;
+               } else {
                        if (host -> group -> statements &&
                            (!host -> named_group ||
                             host -> group != host -> named_group -> group) &&
-                           host -> group != &root_group)
+                           host -> group != root_group)
                                return ISC_R_EXISTS;
-                       host -> group = clone_group (host -> group, MDL);
+                       if (!clone_group (&host -> group, host -> group, MDL))
+                               return ISC_R_NOMEMORY;
                }
                if (!host -> group)
                        return ISC_R_NOMEMORY;
@@ -1258,6 +948,7 @@ isc_result_t dhcp_host_destroy (omapi_object_t *h, const char *file, int line)
 
        /* Currently, this is completely hopeless - have to complete
            reference counting support for server OMAPI objects. */
+       /* XXX okay, that's completed - now what? */
 
        return ISC_R_SUCCESS;
 }
@@ -1437,48 +1128,58 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
        /* Now look for a client identifier. */
        status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
        if (status == ISC_R_SUCCESS) {
-               host = ((struct host_decl *)
-                        hash_lookup (host_uid_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               host = (struct host_decl *)0;
+               host_hash_lookup (&host, host_uid_hash,
+                                 tv -> value -> u.buffer.value,
+                                 tv -> value -> u.buffer.len, MDL);
                omapi_value_dereference (&tv, MDL);
                        
                if (*lp && *lp != (omapi_object_t *)host) {
                        omapi_object_dereference (lp, MDL);
+                       if (host)
+                               host_dereference (&host, MDL);
                        return ISC_R_KEYCONFLICT;
                } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
                        if (*lp)
                            omapi_object_dereference (lp, MDL);
+                       if (host)
+                               host_dereference (&host, MDL);
                        return ISC_R_NOTFOUND;
                } else if (!*lp) {
                        /* XXX fix so that hash lookup itself creates
                           XXX the reference. */
                        omapi_object_reference (lp,
                                                (omapi_object_t *)host, MDL);
+                       host_dereference (&host, MDL);
                }
        }
 
        /* Now look for a hardware address. */
        status = omapi_get_value_str (ref, id, "hardware-address", &tv);
        if (status == ISC_R_SUCCESS) {
-               host = ((struct host_decl *)
-                        hash_lookup (host_hw_addr_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               host = (struct host_decl *)0;
+               host_hash_lookup (&host, host_hw_addr_hash,
+                                 tv -> value -> u.buffer.value,
+                                 tv -> value -> u.buffer.len, MDL);
                omapi_value_dereference (&tv, MDL);
                        
                if (*lp && *lp != (omapi_object_t *)host) {
                        omapi_object_dereference (lp, MDL);
+                       if (host)
+                               host_dereference (&host, MDL);
                        return ISC_R_KEYCONFLICT;
                } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
                        if (*lp)
                            omapi_object_dereference (lp, MDL);
+                       if (host)
+                               host_dereference (&host, MDL);
                        return ISC_R_NOTFOUND;
                } else if (!*lp) {
                        /* XXX fix so that hash lookup itself creates
                           XXX the reference. */
                        omapi_object_reference (lp,
                                                (omapi_object_t *)host, MDL);
+                       host_dereference (&host, MDL);
                }
        }
 
@@ -1488,10 +1189,10 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
                struct lease *l;
 
                /* first find the lease for this ip address */
-               l = ((struct lease *)
-                        hash_lookup (lease_ip_addr_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               l = (struct lease *)0;
+               lease_hash_lookup (&l, lease_ip_addr_hash,
+                                  tv -> value -> u.buffer.value,
+                                  tv -> value -> u.buffer.len, MDL);
                omapi_value_dereference (&tv, MDL);
 
                if (!l && !*lp)
@@ -1499,47 +1200,57 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
 
                if (l) {
                        /* now use that to get a host */
-                       host = ((struct host_decl *)
-                               hash_lookup (host_hw_addr_hash,
-                                            l -> hardware_addr.hbuf,
-                                            l -> hardware_addr.hlen));
+                       host = (struct host_decl *)0;
+                       host_hash_lookup (&host, host_hw_addr_hash,
+                                         l -> hardware_addr.hbuf,
+                                         l -> hardware_addr.hlen, MDL);
                        
                        if (host && *lp && *lp != (omapi_object_t *)host) {
                            omapi_object_dereference (lp, MDL);
+                           if (host)
+                               host_dereference (&host, MDL);
                            return ISC_R_KEYCONFLICT;
                        } else if (!host || (host -> flags &
                                             HOST_DECL_DELETED)) {
+                           if (host)
+                               host_dereference (&host, MDL);
                            if (!*lp)
                                    return ISC_R_NOTFOUND;
                        } else if (!*lp) {
                                /* XXX fix so that hash lookup itself creates
                                   XXX the reference. */
-                               omapi_object_reference (lp,
-                                                       (omapi_object_t *)host,
-                                                       MDL);
+                           omapi_object_reference (lp, (omapi_object_t *)host,
+                                                   MDL);
+                           host_dereference (&host, MDL);
                        }
+                       lease_dereference (&l, MDL);
                }
        }
 
        /* Now look for a name. */
        status = omapi_get_value_str (ref, id, "name", &tv);
        if (status == ISC_R_SUCCESS) {
-               host = ((struct host_decl *)
-                        hash_lookup (host_name_hash,
-                                     tv -> value -> u.buffer.value,
-                                     tv -> value -> u.buffer.len));
+               host = (struct host_decl *)0;
+               host_hash_lookup (&host, host_name_hash,
+                                 tv -> value -> u.buffer.value,
+                                 tv -> value -> u.buffer.len, MDL);
                omapi_value_dereference (&tv, MDL);
                        
                if (*lp && *lp != (omapi_object_t *)host) {
                        omapi_object_dereference (lp, MDL);
+                       if (host)
+                           host_dereference (&host, MDL);
                        return ISC_R_KEYCONFLICT;
                } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
+                       if (host)
+                           host_dereference (&host, MDL);
                        return ISC_R_NOTFOUND;  
                } else if (!*lp) {
                        /* XXX fix so that hash lookup itself creates
                           XXX the reference. */
                        omapi_object_reference (lp,
                                                (omapi_object_t *)host, MDL);
+                       host_dereference (&host, MDL);
                }
        }
 
@@ -1554,15 +1265,16 @@ isc_result_t dhcp_host_create (omapi_object_t **lp,
                               omapi_object_t *id)
 {
        struct host_decl *hp;
-       hp = (struct host_decl *)dmalloc (sizeof (struct host_decl), MDL);
-       if (!hp)
-               return ISC_R_NOMEMORY;
-       memset (hp, 0, sizeof *hp);
-       hp -> refcnt = 0;
-       hp -> type = dhcp_type_host;
-       hp -> group = &root_group;      /* XXX */
+       isc_result_t status;
+       hp = (struct host_decl *)0;
+       status = host_allocate (&hp, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
+       group_reference (&hp -> group, root_group, MDL);
        hp -> flags = HOST_DECL_DYNAMIC;
-       return omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
+       status = omapi_object_reference (lp, (omapi_object_t *)hp, MDL);
+       host_dereference (&hp, MDL);
+       return status;
 }
 
 isc_result_t dhcp_host_remove (omapi_object_t *lp,
@@ -1581,9 +1293,9 @@ isc_result_t dhcp_host_remove (omapi_object_t *lp,
 }
 
 isc_result_t dhcp_pool_set_value  (omapi_object_t *h,
-                                   omapi_object_t *id,
-                                   omapi_data_string_t *name,
-                                   omapi_typed_data_t *value)
+                                  omapi_object_t *id,
+                                  omapi_data_string_t *name,
+                                  omapi_typed_data_t *value)
 {
        struct pool *pool;
        isc_result_t status;
@@ -1608,8 +1320,8 @@ isc_result_t dhcp_pool_set_value  (omapi_object_t *h,
 
 
 isc_result_t dhcp_pool_get_value (omapi_object_t *h, omapi_object_t *id,
-                                  omapi_data_string_t *name,
-                                  omapi_value_t **value)
+                                 omapi_data_string_t *name,
+                                 omapi_value_t **value)
 {
        struct pool *pool;
        isc_result_t status;
@@ -1670,8 +1382,8 @@ isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
 }
 
 isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
-                                     omapi_object_t *id,
-                                     omapi_object_t *h)
+                                    omapi_object_t *id,
+                                    omapi_object_t *h)
 {
        struct pool *pool;
        isc_result_t status;
@@ -1694,7 +1406,7 @@ isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
 }
 
 isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
-                               omapi_object_t *id, omapi_object_t *ref)
+                              omapi_object_t *id, omapi_object_t *ref)
 {
        omapi_value_t *tv = (omapi_value_t *)0;
        isc_result_t status;
@@ -1710,7 +1422,7 @@ isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
 }
 
 isc_result_t dhcp_pool_create (omapi_object_t **lp,
-                               omapi_object_t *id)
+                              omapi_object_t *id)
 {
        return ISC_R_NOTIMPLEMENTED;
 }
@@ -1721,4 +1433,145 @@ isc_result_t dhcp_pool_remove (omapi_object_t *lp,
        return ISC_R_NOTIMPLEMENTED;
 }
 
+isc_result_t dhcp_class_set_value  (omapi_object_t *h,
+                                   omapi_object_t *id,
+                                   omapi_data_string_t *name,
+                                   omapi_typed_data_t *value)
+{
+       struct class *class;
+       isc_result_t status;
+       int foo;
+
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+       class = (struct class *)h;
+
+       /* No values to set yet. */
+
+       /* Try to find some inner object that can take the value. */
+       if (h -> inner && h -> inner -> type -> set_value) {
+               status = ((*(h -> inner -> type -> set_value))
+                         (h -> inner, id, name, value));
+               if (status == ISC_R_SUCCESS || status == ISC_R_UNCHANGED)
+                       return status;
+       }
+                         
+       return ISC_R_NOTFOUND;
+}
+
+
+isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
+                                  omapi_data_string_t *name,
+                                  omapi_value_t **value)
+{
+       struct class *class;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+       class = (struct class *)h;
+
+       /* No values to get yet. */
+
+       /* Try to find some inner object that can provide the value. */
+       if (h -> inner && h -> inner -> type -> get_value) {
+               status = ((*(h -> inner -> type -> get_value))
+                         (h -> inner, id, name, value));
+               if (status == ISC_R_SUCCESS)
+                       return status;
+       }
+       return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
+{
+       struct class *class;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+       class = (struct class *)h;
+
+       /* Can't destroy classs yet. */
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
+                                       const char *name, va_list ap)
+{
+       struct class *class;
+       isc_result_t status;
+       int updatep = 0;
+
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+       class = (struct class *)h;
+
+       /* Can't write classs yet. */
+
+       /* Try to find some inner object that can take the value. */
+       if (h -> inner && h -> inner -> type -> get_value) {
+               status = ((*(h -> inner -> type -> signal_handler))
+                         (h -> inner, name, ap));
+               if (status == ISC_R_SUCCESS)
+                       return status;
+       }
+       if (updatep)
+               return ISC_R_SUCCESS;
+       return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
+                                     omapi_object_t *id,
+                                     omapi_object_t *h)
+{
+       struct class *class;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+       class = (struct class *)h;
+
+       /* Can't stuff class values yet. */
+
+       /* Write out the inner object, if any. */
+       if (h -> inner && h -> inner -> type -> stuff_values) {
+               status = ((*(h -> inner -> type -> stuff_values))
+                         (c, id, h -> inner));
+               if (status == ISC_R_SUCCESS)
+                       return status;
+       }
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_class_lookup (omapi_object_t **lp,
+                               omapi_object_t *id, omapi_object_t *ref)
+{
+       omapi_value_t *tv = (omapi_value_t *)0;
+       isc_result_t status;
+       struct class *class;
+
+       /* Can't look up classs yet. */
+
+       /* If we get to here without finding a class, no valid key was
+          specified. */
+       if (!*lp)
+               return ISC_R_NOKEYS;
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_class_create (omapi_object_t **lp,
+                               omapi_object_t *id)
+{
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_class_remove (omapi_object_t *lp,
+                               omapi_object_t *id)
+{
+       return ISC_R_NOTIMPLEMENTED;
+}
+
 /* vim: set tabstop=8: */
index 055b4fe223d35ab1fd7011e8345f7c42213a102a..65cc3619a02e4f804313d0f5e82b9fa00c21beba 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: stables.c,v 1.11 2000/05/02 00:25:10 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: stables.c,v 1.12 2000/05/16 23:03:49 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -716,9 +716,9 @@ void initialize_server_option_spaces()
                log_fatal ("Can't allocate agent option hash table.");
        for (i = 0; i < 256; i++) {
                agent_universe.options [i] = &agent_options [i];
-               add_hash (agent_universe.hash,
-                         (const unsigned char *)agent_options [i].name, 0,
-                         (unsigned char *)&agent_options [i]);
+               option_hash_add (agent_universe.hash,
+                                agent_options [i].name, 0,
+                                &agent_options [i], MDL);
        }
 
        /* Set up the server option universe... */
@@ -742,18 +742,16 @@ void initialize_server_option_spaces()
                log_fatal ("Can't allocate server option hash table.");
        for (i = 0; i < 256; i++) {
                server_universe.options [i] = &server_options [i];
-               add_hash (server_universe.hash,
-                         (const unsigned char *)server_options [i].name, 0,
-                         (unsigned char *)&server_options [i]);
+               option_hash_add (server_universe.hash,
+                                server_options [i].name, 0,
+                                &server_options [i], MDL);
        }
 
        /* Add the server and agent option spaces to the option space hash. */
-       add_hash (universe_hash,
-                 (const unsigned char *)agent_universe.name, 0,
-                 (unsigned char *)&agent_universe);
-       add_hash (universe_hash,
-                 (const unsigned char *)server_universe.name, 0,
-                 (unsigned char *)&server_universe);
+       universe_hash_add (universe_hash,
+                          agent_universe.name, 0, &agent_universe, MDL);
+       universe_hash_add (universe_hash,
+                          server_universe.name, 0, &server_universe, MDL);
 
        /* Make the server universe the configuration option universe. */
        config_universe = &server_universe;