]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Add support for creating named groups (but not yet for stuffing
authorTed Lemon <source@isc.org>
Wed, 29 Sep 1999 00:00:35 +0000 (00:00 +0000)
committerTed Lemon <source@isc.org>
Wed, 29 Sep 1999 00:00:35 +0000 (00:00 +0000)
  values into them).
- Fix key conflict detection so that it's possible to send an update
  that contains more than one key, so long as each key doesn't match a
  different object.
- Fix numerous bugs in various update functions.

server/omapi.c

index 5179ada73182acaf0ff2b890e852459e18c89436..ad7161c4d930c4c3d2e77595c7a3a3fd08d197f5 100644 (file)
@@ -29,7 +29,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: omapi.c,v 1.7 1999/09/16 05:12:38 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: omapi.c,v 1.8 1999/09/29 00:00:35 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,6 +59,20 @@ void dhcp_db_objects_setup ()
                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);
+       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,
@@ -69,7 +83,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_host_lookup, 
                                             dhcp_host_create,
                                             dhcp_host_remove);
-if (status != ISC_R_SUCCESS)
+       if (status != ISC_R_SUCCESS)
                log_fatal ("Can't register host object type: %s",
                           isc_result_totext (status));
 
@@ -292,6 +306,7 @@ isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
 {
        struct lease *lease;
        isc_result_t status;
+       int updatep = 0;
 
        if (h -> type != dhcp_type_lease)
                return ISC_R_INVALIDARG;
@@ -304,6 +319,7 @@ isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
                        return ISC_R_INVALIDARG;
                if (!write_lease (lease))
                        return ISC_R_IOERROR;
+               updatep = 1;
        }
 
        /* Try to find some inner object that can take the value. */
@@ -313,6 +329,8 @@ isc_result_t dhcp_lease_signal_handler (omapi_object_t *h,
                if (status == ISC_R_SUCCESS)
                        return status;
        }
+       if (updatep)
+               return ISC_R_SUCCESS;
        return ISC_R_NOTFOUND;
 }
 
@@ -493,14 +511,6 @@ 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) {
-               /* If we already have a value, flag an error - only one
-                  key can be used for lookups at a time. */
-               if (*lp) {
-                       omapi_object_dereference (lp, "dhcp_lease_lookup");
-                       omapi_value_dereference (&tv, "dhcp_lease_lookup");
-                       return ISC_R_INVALIDARG;
-               }
-
                lease = ((struct lease *)
                         hash_lookup (lease_ip_addr_hash,
                                      tv -> value -> u.buffer.value,
@@ -508,65 +518,77 @@ isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
 
                omapi_value_dereference (&tv, "dhcp_lease_lookup");
 
-               if (!lease)
+               /* If we already have a lease, and it's not the same one,
+                  then the query was invalid. */
+               if (*lp && *lp != (omapi_object_t *)lease) {
+                       omapi_object_dereference (lp, "dhcp_lease_lookup");
+                       return ISC_R_KEYCONFLICT;
+               } else if (!lease) {
+                       if (*lp)
+                               omapi_object_dereference (lp,
+                                                         "dhcp_lease_lookup");
                        return ISC_R_NOTFOUND;
-
-               /* XXX fix so that hash lookup itself creates
-                  XXX the reference. */
-               omapi_object_reference (lp, (omapi_object_t *)lease,
-                                       "dhcp_lease_lookup");
+               } else if (!*lp)
+                       /* XXX fix so that hash lookup itself creates
+                          XXX the reference. */
+                       omapi_object_reference (lp, (omapi_object_t *)lease,
+                                               "dhcp_lease_lookup");
        }
 
        /* Now look for a client identifier. */
        status = omapi_get_value_str (ref, id, "dhcp-client-identifier", &tv);
        if (status == ISC_R_SUCCESS) {
-               if (*lp) {
-                       omapi_object_dereference (lp, "dhcp_lease_lookup");
-                       omapi_value_dereference (&tv, "dhcp_lease_lookup");
-                       return ISC_R_INVALIDARG;
-               }
-
                lease = ((struct lease *)
                         hash_lookup (lease_uid_hash,
                                      tv -> value -> u.buffer.value,
                                      tv -> value -> u.buffer.len));
                omapi_value_dereference (&tv, "dhcp_lease_lookup");
                        
-               if (!lease)
+               if (*lp && *lp != (omapi_object_t *)lease) {
+                       omapi_object_dereference (lp, "dhcp_lease_lookup");
+                       return ISC_R_KEYCONFLICT;
+               } else if (!lease) {
+                       if (*lp)
+                           omapi_object_dereference (lp, "dhcp_lease_lookup");
                        return ISC_R_NOTFOUND;
-               if (lease -> n_uid)
+               } else if (lease -> n_uid) {
+                       if (*lp)
+                           omapi_object_dereference (lp, "dhcp_lease_lookup");
                        return ISC_R_MULTIPLE;
-
-               /* XXX fix so that hash lookup itself creates
-                  XXX the reference. */
-               omapi_object_reference (lp, (omapi_object_t *)lease,
-                                       "dhcp_lease_lookup");
+               } else if (!*lp) {
+                       /* XXX fix so that hash lookup itself creates
+                          XXX the reference. */
+                       omapi_object_reference (lp, (omapi_object_t *)lease,
+                                               "dhcp_lease_lookup");
+               }
        }
 
        /* Now look for a hardware address. */
        status = omapi_get_value_str (ref, id, "hardware-address", &tv);
        if (status == ISC_R_SUCCESS) {
-               if (*lp) {
-                       omapi_object_dereference (lp, "dhcp_lease_lookup");
-                       omapi_value_dereference (&tv, "dhcp_lease_lookup");
-                       return ISC_R_INVALIDARG;
-               }
-
                lease = ((struct lease *)
                         hash_lookup (lease_hw_addr_hash,
                                      tv -> value -> u.buffer.value,
                                      tv -> value -> u.buffer.len));
                omapi_value_dereference (&tv, "dhcp_lease_lookup");
                        
-               if (!lease)
+               if (*lp && *lp != (omapi_object_t *)lease) {
+                       omapi_object_dereference (lp, "dhcp_lease_lookup");
+                       return ISC_R_KEYCONFLICT;
+               } else if (!lease) {
+                       if (*lp)
+                           omapi_object_dereference (lp, "dhcp_lease_lookup");
                        return ISC_R_NOTFOUND;
-               if (lease -> n_hw)
+               } else if (lease -> n_hw) {
+                       if (*lp)
+                           omapi_object_dereference (lp, "dhcp_lease_lookup");
                        return ISC_R_MULTIPLE;
-
-               /* XXX fix so that hash lookup itself creates
-                  XXX the reference. */
-               omapi_object_reference (lp, (omapi_object_t *)lease,
-                                       "dhcp_lease_lookup");
+               } else if (!*lp) {
+                       /* XXX fix so that hash lookup itself creates
+                          XXX the reference. */
+                       omapi_object_reference (lp, (omapi_object_t *)lease,
+                                               "dhcp_lease_lookup");
+               }
        }
 
        /* If we get to here without finding a lease, no valid key was
@@ -588,26 +610,290 @@ isc_result_t dhcp_lease_remove (omapi_object_t *lp,
        return ISC_R_NOTIMPLEMENTED;
 }
 
-#if 0
-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 *, char *);
-isc_result_t dhcp_group_signal_handler (omapi_object_t *, 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 *);
-#endif
-
-isc_result_t dhcp_host_set_value  (omapi_object_t *h,
+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 = malloc (value -> u.buffer.len + 1);
+                       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;
+       }
+
+       /* 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,
+                                               "dhcp_group_get_value");
+
+       /* 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, char *name)
+{
+       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,
+                                         group -> name,
+                                         strlen (group -> name)));
+                       if (t) {
+                               delete_hash_entry (group_name_hash,
+                                                  group -> name,
+                                                  strlen (group -> name));
+                               --group -> refcnt;
+                       }
+               }
+               free (group -> name);
+               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,
+                                       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 = malloc (strlen (hnbuf) + 1);
+                       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, "dhcp_group_lookup");
+               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, "dhcp_group_lookup");
+                       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, "dhcp_group_lookup");
+
+                       /* 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, "dhcp_group_lookup");
+                           return ISC_R_KEYCONFLICT;
+                       } else if (!group) {
+                           omapi_object_dereference (lp, "dhcp_group_lookup");
+                           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,
+                                                   "dhcp_group_lookup");
+                       }
+               } 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_INVALIDARG;
+
+       if (((struct group_object *)(*lp)) -> flags & GROUP_OBJECT_DELETED) {
+               omapi_object_dereference (lp, "dhcp_group_lookup");
+               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),
+                                         "dhcp_group_create");
+       if (!group)
+               return ISC_R_NOMEMORY;
+       memset (group, 0, sizeof *group);
+       group -> refcnt = 0;
+       group -> type = dhcp_type_group;
+       return omapi_object_reference (lp, (omapi_object_t *)group,
+                                      "dhcp_group_create");
+}
+
+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))
+               return ISC_R_IOERROR;
+
+       status = dhcp_group_destroy ((omapi_object_t *)group,
+                                    "dhcp_group_remove");
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_host_set_value  (omapi_object_t *h,
+                                  omapi_object_t *id,
+                                  omapi_data_string_t *name,
+                                  omapi_typed_data_t *value)
 {
        struct host_decl *host;
        isc_result_t status;
@@ -636,6 +922,31 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                return ISC_R_SUCCESS;
        }
 
+       if (!omapi_ds_strcmp (name, "group")) {
+               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));
+                       if (!group || (group -> flags & GROUP_OBJECT_DELETED))
+                               return ISC_R_NOTFOUND;
+                       host -> group = group -> group;
+                       if (host -> named_group)
+                               omapi_object_dereference
+                                       ((omapi_object_t **)
+                                        &host -> named_group,
+                                        "dhcp_host_set_value");
+                       omapi_object_reference ((omapi_object_t **)
+                                               &host -> named_group,
+                                               (omapi_object_t *)group,
+                                               "dhcp_host_set_value");
+               } else
+                       return ISC_R_INVALIDARG;
+               return ISC_R_SUCCESS;
+       }
+
        if (!omapi_ds_strcmp (name, "hardware-address")) {
                if (host -> interface.hlen)
                        return ISC_R_EXISTS;
@@ -676,17 +987,17 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                        return ISC_R_EXISTS;
                if (value -> type == omapi_datatype_data ||
                    value -> type == omapi_datatype_string) {
-                       host -> client_identifier.len = value -> u.buffer.len;
                        if (!buffer_allocate
                            (&host -> client_identifier.buffer,
-                            host -> client_identifier.len,
+                            value -> u.buffer.len,
                             "dhcp_host_set_value"))
                                return ISC_R_NOMEMORY;
                        host -> client_identifier.data =
                                &host -> client_identifier.buffer -> data [0];
                        memcpy (host -> client_identifier.data,
                                value -> u.buffer.value,
-                               host -> client_identifier.len);
+                               value -> u.buffer.len);
+                       host -> client_identifier.len = value -> u.buffer.len;
                } else
                        return ISC_R_INVALIDARG;
                return ISC_R_SUCCESS;
@@ -703,8 +1014,7 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                        if (!buffer_allocate (&ds.buffer, ds.len,
                                              "dhcp_host_set_value"))
                                return ISC_R_NOMEMORY;
-                       ds.data = (&host -> client_identifier.buffer ->
-                                  data [0]);
+                       ds.data = (&ds.buffer -> data [0]);
                        memcpy (ds.data, value -> u.buffer.value, ds.len);
                        if (!option_cache (&host -> fixed_addr,
                                           &ds, (struct expression *)0,
@@ -826,15 +1136,17 @@ isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
 {
        struct host_decl *host;
        isc_result_t status;
+       int updatep = 0;
 
        if (h -> type != dhcp_type_host)
                return ISC_R_INVALIDARG;
        host = (struct host_decl *)h;
 
        if (!strcmp (name, "updated")) {
-               if (host -> interface.hlen == 0 ||
-                   host -> interface.htype == 0 ||
-                   host -> interface.hlen > 16)
+               if ((host -> interface.hlen == 0 ||
+                    host -> interface.htype == 0 ||
+                    host -> interface.hlen > 16) &&
+                   !host -> client_identifier.len)
                        return ISC_R_INVALIDARG;
 
                if (!host -> name) {
@@ -850,6 +1162,7 @@ isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
                status = enter_host (host, 1, 1);
                if (status != ISC_R_SUCCESS)
                        return status;
+               updatep = 1;
        }
 
        /* Try to find some inner object that can take the value. */
@@ -859,6 +1172,8 @@ isc_result_t dhcp_host_signal_handler (omapi_object_t *h,
                if (status == ISC_R_SUCCESS)
                        return status;
        }
+       if (updatep)
+               return ISC_R_SUCCESS;
        return ISC_R_NOTFOUND;
 }
 
@@ -912,33 +1227,39 @@ isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
                        return status;
        }
 
-       status = omapi_connection_put_name (c, "name");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_string (c, host -> name);
-       if (status != ISC_R_SUCCESS)
-               return status;
+       if (host -> name) {
+               status = omapi_connection_put_name (c, "name");
+               if (status != ISC_R_SUCCESS)
+                       return status;
+               status = omapi_connection_put_string (c, host -> name);
+               if (status != ISC_R_SUCCESS)
+                       return status;
+       }
 
-       status = omapi_connection_put_name (c, "hardware-address");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32 (c, host -> interface.hlen);
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_copyin (c, host -> interface.haddr,
-                                         host -> interface.hlen);
-       if (status != ISC_R_SUCCESS)
-               return status;
+       if (host -> interface.hlen) {
+               status = omapi_connection_put_name (c, "hardware-address");
+               if (status != ISC_R_SUCCESS)
+                       return status;
+               status = omapi_connection_put_uint32 (c,
+                                                     host -> interface.hlen);
+               if (status != ISC_R_SUCCESS)
+                       return status;
+               status = omapi_connection_copyin (c, host -> interface.haddr,
+                                                 host -> interface.hlen);
+               if (status != ISC_R_SUCCESS)
+                       return status;
 
-       status = omapi_connection_put_name (c, "hardware-type");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32 (c, sizeof (int));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32 (c, host -> interface.htype);
-       if (status != ISC_R_SUCCESS)
-               return status;
+               status = omapi_connection_put_name (c, "hardware-type");
+               if (status != ISC_R_SUCCESS)
+                       return status;
+               status = omapi_connection_put_uint32 (c, sizeof (int));
+               if (status != ISC_R_SUCCESS)
+                       return status;
+               status = omapi_connection_put_uint32 (c,
+                                                     host -> interface.htype);
+               if (status != ISC_R_SUCCESS)
+                       return status;
+       }
 
        /* Write out the inner object, if any. */
        if (h -> inner && h -> inner -> type -> stuff_values) {
@@ -977,60 +1298,55 @@ 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) {
-               if (*lp) {
-                       omapi_object_dereference (lp, "dhcp_host_lookup");
-                       omapi_value_dereference (&tv, "dhcp_host_lookup");
-                       return ISC_R_INVALIDARG;
-               }
-
                host = ((struct host_decl *)
                         hash_lookup (host_uid_hash,
                                      tv -> value -> u.buffer.value,
                                      tv -> value -> u.buffer.len));
                omapi_value_dereference (&tv, "dhcp_host_lookup");
                        
-               if (!host)
+               if (*lp && *lp != (omapi_object_t *)host) {
+                       omapi_object_dereference (lp, "dhcp_host_lookup");
+                       return ISC_R_KEYCONFLICT;
+               } else if (!host) {
+                       if (*lp)
+                           omapi_object_dereference (lp, "dhcp_host_lookup");
                        return ISC_R_NOTFOUND;
-
-               /* XXX fix so that hash lookup itself creates
-                  XXX the reference. */
-               omapi_object_reference (lp, (omapi_object_t *)host,
-                                       "dhcp_host_lookup");
+               } else if (!*lp) {
+                       /* XXX fix so that hash lookup itself creates
+                          XXX the reference. */
+                       omapi_object_reference (lp, (omapi_object_t *)host,
+                                               "dhcp_host_lookup");
+               }
        }
 
        /* Now look for a hardware address. */
        status = omapi_get_value_str (ref, id, "hardware-address", &tv);
        if (status == ISC_R_SUCCESS) {
-               if (*lp) {
-                       omapi_object_dereference (lp, "dhcp_host_lookup");
-                       omapi_value_dereference (&tv, "dhcp_host_lookup");
-                       return ISC_R_INVALIDARG;
-               }
-
                host = ((struct host_decl *)
                         hash_lookup (host_hw_addr_hash,
                                      tv -> value -> u.buffer.value,
                                      tv -> value -> u.buffer.len));
                omapi_value_dereference (&tv, "dhcp_host_lookup");
                        
-               if (!host)
+               if (*lp && *lp != (omapi_object_t *)host) {
+                       omapi_object_dereference (lp, "dhcp_host_lookup");
+                       return ISC_R_KEYCONFLICT;
+               } else if (!host) {
+                       if (*lp)
+                           omapi_object_dereference (lp, "dhcp_host_lookup");
                        return ISC_R_NOTFOUND;
-
-               /* XXX fix so that hash lookup itself creates
-                  XXX the reference. */
-               omapi_object_reference (lp, (omapi_object_t *)host,
-                                       "dhcp_host_lookup");
+               } else if (!*lp) {
+                       /* XXX fix so that hash lookup itself creates
+                          XXX the reference. */
+                       omapi_object_reference (lp, (omapi_object_t *)host,
+                                               "dhcp_host_lookup");
+               }
        }
 
        /* Now look for an ip address. */
        status = omapi_get_value_str (ref, id, "ip-address", &tv);
        if (status == ISC_R_SUCCESS) {
                struct lease *l;
-               if (*lp) {
-                       omapi_object_dereference (lp, "dhcp_host_lookup");
-                       omapi_value_dereference (&tv, "dhcp_host_lookup");
-                       return ISC_R_INVALIDARG;
-               }
 
                /* first find the lease for this ip address */
                l = ((struct lease *)
@@ -1039,22 +1355,29 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
                                      tv -> value -> u.buffer.len));
                omapi_value_dereference (&tv, "dhcp_host_lookup");
 
-               if (!l)
+               if (!l && !*lp)
                        return ISC_R_NOTFOUND;
 
-               /* now use that to get a host */
-               host = ((struct host_decl *)
-                        hash_lookup (host_hw_addr_hash,
-                                     l -> hardware_addr.haddr,
-                                     l -> hardware_addr.hlen));
+               if (l) {
+                       /* now use that to get a host */
+                       host = ((struct host_decl *)
+                               hash_lookup (host_hw_addr_hash,
+                                            l -> hardware_addr.haddr,
+                                            l -> hardware_addr.hlen));
                        
-               if (!host)
-                       return ISC_R_NOTFOUND;
-
-               /* XXX fix so that hash lookup itself creates
-                  XXX the reference. */
-               omapi_object_reference (lp, (omapi_object_t *)host,
-                                       "dhcp_host_lookup");
+                       if (host && *lp && *lp != (omapi_object_t *)host) {
+                           omapi_object_dereference (lp, "dhcp_host_lookup");
+                           return ISC_R_KEYCONFLICT;
+                       } else if (!host) {
+                           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,
+                                                   "dhcp_host_lookup");
+                       }
+               }
        }
 
        /* If we get to here without finding a host, no valid key was
@@ -1161,6 +1484,7 @@ isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
 {
        struct pool *pool;
        isc_result_t status;
+       int updatep = 0;
 
        if (h -> type != dhcp_type_pool)
                return ISC_R_INVALIDARG;
@@ -1175,6 +1499,8 @@ isc_result_t dhcp_pool_signal_handler (omapi_object_t *h,
                if (status == ISC_R_SUCCESS)
                        return status;
        }
+       if (updatep)
+               return ISC_R_SUCCESS;
        return ISC_R_NOTFOUND;
 }