]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Move common omapi support into common code.
authorTed Lemon <source@isc.org>
Tue, 16 May 2000 23:13:34 +0000 (23:13 +0000)
committerTed Lemon <source@isc.org>
Tue, 16 May 2000 23:13:34 +0000 (23:13 +0000)
client/omapi.c [deleted file]
common/comapi.c [new file with mode: 0644]

diff --git a/client/omapi.c b/client/omapi.c
deleted file mode 100644 (file)
index fc9e4e2..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* omapi.c
-
-   OMAPI object interfaces for the DHCP client. */
-
-/*
- * Copyright (c) 2000 The Internet Software Consortium
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of The Internet Software Consortium nor the names
- *    of its contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
- * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This software has been written for the Internet Software Consortium
- * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
- * To learn more about the Internet Software Consortium, see
- * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
- * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
- * ``http://www.nominum.com''.
- */
-
-#ifndef lint
-static char copyright[] =
-"$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>
diff --git a/common/comapi.c b/common/comapi.c
new file mode 100644 (file)
index 0000000..acca60d
--- /dev/null
@@ -0,0 +1,1014 @@
+/* omapi.c
+
+   OMAPI object interfaces for the DHCP server. */
+
+/*
+ * Copyright (c) 1999-2000 Internet Software Consortium.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ *    of its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This software has been written for the Internet Software Consortium
+ * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
+ * To learn more about the Internet Software Consortium, see
+ * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
+ * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
+ * ``http://www.nominum.com''.
+ */
+
+/* Many, many thanks to Brian Murrell and BCtel for this code - BCtel
+   provided the funding that resulted in this code and the entire
+   OMAPI support library being written, and Brian helped brainstorm
+   and refine the requirements.  To the extent that this code is
+   useful, you have Brian and BCtel to thank.  Any limitations in the
+   code are a result of mistakes on my part.  -- Ted Lemon */
+
+#ifndef lint
+static char copyright[] =
+"$Id: comapi.c,v 1.1 2000/05/16 23:12:09 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>
+
+int (*dhcp_interface_shutdown_hook) (struct interface_info *);
+
+omapi_object_type_t *dhcp_type_interface;
+omapi_object_type_t *dhcp_type_group;
+omapi_object_type_t *dhcp_type_shared_network;
+omapi_object_type_t *dhcp_type_subnet;
+
+void dhcp_common_objects_setup ()
+{
+       isc_result_t 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, 0, 0,
+                                            sizeof (struct group));
+       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_subnet,
+                                            "subnet",
+                                            dhcp_subnet_set_value,
+                                            dhcp_subnet_get_value,
+                                            dhcp_subnet_destroy,
+                                            dhcp_subnet_signal_handler,
+                                            dhcp_subnet_stuff_values,
+                                            dhcp_subnet_lookup, 
+                                            dhcp_subnet_create,
+                                            dhcp_subnet_remove, 0, 0,
+                                            sizeof (struct subnet));
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Can't register subnet object type: %s",
+                          isc_result_totext (status));
+
+       status = omapi_object_type_register
+               (&dhcp_type_shared_network,
+                "shared-network",
+                dhcp_shared_network_set_value,
+                dhcp_shared_network_get_value,
+                dhcp_shared_network_destroy,
+                dhcp_shared_network_signal_handler,
+                dhcp_shared_network_stuff_values,
+                dhcp_shared_network_lookup, 
+                dhcp_shared_network_create,
+                dhcp_shared_network_remove, 0, 0,
+                sizeof (struct shared_network));
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Can't register shared network object type: %s",
+                          isc_result_totext (status));
+
+       status = omapi_object_type_register (&dhcp_type_interface,
+                                            "interface",
+                                            dhcp_interface_set_value,
+                                            dhcp_interface_get_value,
+                                            dhcp_interface_destroy,
+                                            dhcp_interface_signal_handler,
+                                            dhcp_interface_stuff_values,
+                                            dhcp_interface_lookup, 
+                                            dhcp_interface_create,
+                                            dhcp_interface_remove,
+                                            0, 0,
+                                            sizeof (struct interface_info));
+       if (status != ISC_R_SUCCESS)
+               log_fatal ("Can't register interface object type: %s",
+                          isc_result_totext (status));
+}
+
+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) {
+                       if (!clone_group (&group -> group, root_group, MDL))
+                               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 *)0;
+                       if (group_hash_lookup (&t, group_name_hash,
+                                              group -> name,
+                                              strlen (group -> name), MDL)) {
+                               group_hash_delete (group_name_hash,
+                                                  group -> name,
+                                                  strlen (group -> name),
+                                                  MDL);
+                               group_object_dereference (&t, MDL);
+                       }
+               }
+               dfree (group -> name, file, line);
+               group -> name = (char *)0;
+       }
+       if (group -> group)
+               group_dereference (&group -> group, MDL);
+
+       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) {
+               group = (struct group_object *)0;
+               if (group_name_hash &&
+                   group_hash_lookup (&group, group_name_hash,
+                                      tv -> value -> u.buffer.value,
+                                      tv -> value -> u.buffer.len, MDL)) {
+                       omapi_value_dereference (&tv, MDL);
+
+                       if (*lp && *lp != (omapi_object_t *)group) {
+                           group_object_dereference (&group, MDL);
+                           omapi_object_dereference (lp, MDL);
+                           return ISC_R_KEYCONFLICT;
+                       } else if (!*lp) {
+                           /* XXX fix so that hash lookup itself creates
+                              XXX the reference. */
+                           omapi_object_reference (lp,
+                                                   (omapi_object_t *)group,
+                                                   MDL);
+                           group_object_dereference (&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;
+       isc_result_t status;
+       group = (struct group_object *)0;
+
+       status = group_object_allocate (&group, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
+       memset (group, 0, sizeof *group);
+       group -> flags = GROUP_OBJECT_DYNAMIC;
+       status = omapi_object_reference (lp, (omapi_object_t *)group, MDL);
+       group_object_dereference (&group, MDL);
+       return status;
+}
+
+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 (group_write_hook) {
+               if (!(*group_write_hook) (group))
+                       return ISC_R_IOERROR;
+       }
+
+       status = dhcp_group_destroy ((omapi_object_t *)group, MDL);
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_subnet_set_value  (omapi_object_t *h,
+                                    omapi_object_t *id,
+                                    omapi_data_string_t *name,
+                                    omapi_typed_data_t *value)
+{
+       struct subnet *subnet;
+       isc_result_t status;
+       int foo;
+
+       if (h -> type != dhcp_type_subnet)
+               return ISC_R_INVALIDARG;
+       subnet = (struct subnet *)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_subnet_get_value (omapi_object_t *h, omapi_object_t *id,
+                                   omapi_data_string_t *name,
+                                   omapi_value_t **value)
+{
+       struct subnet *subnet;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_subnet)
+               return ISC_R_INVALIDARG;
+       subnet = (struct subnet *)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_subnet_destroy (omapi_object_t *h, const char *file, int line)
+{
+       struct subnet *subnet;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_subnet)
+               return ISC_R_INVALIDARG;
+       subnet = (struct subnet *)h;
+
+       /* Can't destroy subnets yet. */
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_subnet_signal_handler (omapi_object_t *h,
+                                        const char *name, va_list ap)
+{
+       struct subnet *subnet;
+       isc_result_t status;
+       int updatep = 0;
+
+       if (h -> type != dhcp_type_subnet)
+               return ISC_R_INVALIDARG;
+       subnet = (struct subnet *)h;
+
+       /* Can't write subnets 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_subnet_stuff_values (omapi_object_t *c,
+                                      omapi_object_t *id,
+                                      omapi_object_t *h)
+{
+       struct subnet *subnet;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_subnet)
+               return ISC_R_INVALIDARG;
+       subnet = (struct subnet *)h;
+
+       /* Can't stuff subnet 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_subnet_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 subnet *subnet;
+
+       /* Can't look up subnets yet. */
+
+       /* If we get to here without finding a subnet, no valid key was
+          specified. */
+       if (!*lp)
+               return ISC_R_NOKEYS;
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_subnet_create (omapi_object_t **lp,
+                                omapi_object_t *id)
+{
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_subnet_remove (omapi_object_t *lp,
+                              omapi_object_t *id)
+{
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_shared_network_set_value  (omapi_object_t *h,
+                                            omapi_object_t *id,
+                                            omapi_data_string_t *name,
+                                            omapi_typed_data_t *value)
+{
+       struct shared_network *shared_network;
+       isc_result_t status;
+       int foo;
+
+       if (h -> type != dhcp_type_shared_network)
+               return ISC_R_INVALIDARG;
+       shared_network = (struct shared_network *)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_shared_network_get_value (omapi_object_t *h,
+                                           omapi_object_t *id,
+                                           omapi_data_string_t *name,
+                                           omapi_value_t **value)
+{
+       struct shared_network *shared_network;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_shared_network)
+               return ISC_R_INVALIDARG;
+       shared_network = (struct shared_network *)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_shared_network_destroy (omapi_object_t *h,
+                                         const char *file, int line)
+{
+       struct shared_network *shared_network;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_shared_network)
+               return ISC_R_INVALIDARG;
+       shared_network = (struct shared_network *)h;
+
+       /* Can't destroy shared_networks yet. */
+
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_shared_network_signal_handler (omapi_object_t *h,
+                                                const char *name,
+                                                va_list ap)
+{
+       struct shared_network *shared_network;
+       isc_result_t status;
+       int updatep = 0;
+
+       if (h -> type != dhcp_type_shared_network)
+               return ISC_R_INVALIDARG;
+       shared_network = (struct shared_network *)h;
+
+       /* Can't write shared_networks 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_shared_network_stuff_values (omapi_object_t *c,
+                                              omapi_object_t *id,
+                                              omapi_object_t *h)
+{
+       struct shared_network *shared_network;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_shared_network)
+               return ISC_R_INVALIDARG;
+       shared_network = (struct shared_network *)h;
+
+       /* Can't stuff shared_network 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_shared_network_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 shared_network *shared_network;
+
+       /* Can't look up shared_networks yet. */
+
+       /* If we get to here without finding a shared_network, no valid key was
+          specified. */
+       if (!*lp)
+               return ISC_R_NOKEYS;
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_shared_network_create (omapi_object_t **lp,
+                                        omapi_object_t *id)
+{
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_shared_network_remove (omapi_object_t *lp,
+                                        omapi_object_t *id)
+{
+       return ISC_R_NOTIMPLEMENTED;
+}
+
+isc_result_t dhcp_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) &&
+                   value -> u.buffer.len < sizeof interface -> name) {
+                       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 dhcp_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 dhcp_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)
+               dfree (interface -> ifp, file, line);
+       return ISC_R_SUCCESS;
+}
+
+isc_result_t dhcp_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;
+       isc_result_t status;
+
+       if (h -> type != dhcp_type_interface)
+               return ISC_R_INVALIDARG;
+
+       /* This code needs some rethinking.   It doesn't test against
+          a signal name, and it just kind of bulls into doing something
+          that may or may not be appropriate. */
+#if 0
+       interface = (struct interface_info *)h;
+
+       if (interfaces) {
+               interface_reference (&interface -> next, interfaces, MDL);
+               interface_dereference (&interfaces, MDL);
+       }
+       interface_reference (&interfaces, interface, MDL);
+
+       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, 0, 0);
+               }
+       }
+       return ISC_R_SUCCESS;
+#endif
+       /* 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;
+       }
+       return ISC_R_NOTFOUND;
+}
+
+isc_result_t dhcp_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 dhcp_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 dhcp_interface_create (omapi_object_t **lp,
+                                   omapi_object_t *id)
+{
+       struct interface_info *hp;
+       isc_result_t status;
+       
+       hp = (struct interface_info *)0;
+       status = interface_allocate (&hp, MDL);
+       if (status != ISC_R_SUCCESS)
+               return status;
+       hp -> flags = INTERFACE_REQUESTED;
+       status = interface_reference ((struct interface_info **)lp, hp, MDL);
+       interface_dereference (&hp, MDL);
+       return status;
+}
+
+isc_result_t dhcp_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 (ip == interface) {
+                       if (last) {
+                               interface_dereference (&last -> next, MDL);
+                               if (ip -> next)
+                                       interface_reference (&last -> next,
+                                                            ip -> next, MDL);
+                       } else {
+                               interface_dereference (&interfaces, MDL);
+                               if (ip -> next)
+                                       interface_reference (&interfaces,
+                                                            ip -> next, MDL);
+                       }
+                       if (ip -> next)
+                               interface_dereference (&ip -> next, MDL);
+                       break;
+               }
+               last = ip;
+       }
+       if (!ip)
+               return ISC_R_NOTFOUND;
+
+       /* add the interface to the dummy_interface list */
+       if (dummy_interfaces) {
+               interface_reference (&interface -> next,
+                                    dummy_interfaces, MDL);
+               interface_dereference (&dummy_interfaces, MDL);
+       }
+       interface_reference (&dummy_interfaces, interface, MDL);
+
+       /* do a DHCPRELEASE */
+       if (dhcp_interface_shutdown_hook)
+               (*dhcp_interface_shutdown_hook) (interface);
+
+       /* remove the io object */
+       omapi_unregister_io_object ((omapi_object_t *)interface);
+
+       if_deregister_send (interface);
+       if_deregister_receive (interface);
+
+       return ISC_R_SUCCESS;
+}