]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master]
authorShawn Routhier <sar@isc.org>
Thu, 6 Jun 2013 01:15:49 +0000 (18:15 -0700)
committerShawn Routhier <sar@isc.org>
Thu, 6 Jun 2013 01:15:49 +0000 (18:15 -0700)
Modify the class and subclass code to allow for dynamic addition and
removal of subclasses.  See 27452 for details.

RELNOTES
includes/omapip/omapip.h
omapip/buffer.c
server/confpars.c
server/mdb.c
server/omapi.c

index d7d4c1ea9f3f7e971db00c32c1abeaa9885f69af..d5f9305c90799b4a8fad71f671a85b851a696418 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -87,6 +87,11 @@ work on other platforms. Please report any problems and suggested fixes to
   Thanks to Paolo Pellegrino for finding the issue and a suggestion
   for the patch.
   [ISC-Bugs #33351]
+
+- Fix several problems with using OMAPI to manipulate class and subclass
+  objects.
+  [ISC-Bugs #27452]
+
                        Changes since 4.2.4
 
 - Correct code to calculate timing values in client to compare
index cbdc40d4f768d7cdc4b0a2f1c8c1cd46f918b25b..05ca6c415620e74ece37c9cc252e3dbd46e9d170 100644 (file)
@@ -3,7 +3,8 @@
    Definitions for the object management API and protocol... */
 
 /*
- * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2013 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -353,7 +354,9 @@ isc_result_t omapi_connection_put_name (omapi_object_t *, const char *);
 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_connection_put_named_uint32 (omapi_object_t *,
+                                               const char *,
+                                               u_int32_t);
 isc_result_t omapi_listen (omapi_object_t *, unsigned, int);
 isc_result_t omapi_listen_addr (omapi_object_t *,
                                omapi_addr_t *, int);
index 4104cfb7f4f5013ee3ffecf23f7e97b5fefd2b5c..518f6d3784a6da4c5a09e49c9742aa31ae2c3ab6 100644 (file)
@@ -3,7 +3,7 @@
    Buffer access functions for the object management protocol... */
 
 /*
- * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2012-2013 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004,2005,2007 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
@@ -720,3 +720,22 @@ isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h)
                return status;
        return omapi_connection_put_uint32 (c, handle);
 }
+
+isc_result_t omapi_connection_put_named_uint32 (omapi_object_t *c,
+                                               const char *name,
+                                               u_int32_t value)
+{
+       isc_result_t status;
+
+       status = omapi_connection_put_name(c, name);
+       if (status != ISC_R_SUCCESS)
+               return (status);
+
+       status = omapi_connection_put_uint32(c, sizeof(u_int32_t));
+       if (status != ISC_R_SUCCESS)
+               return (status);
+
+       status = omapi_connection_put_uint32(c, value);
+       return (status);
+}
+
index 47422e5dfad821f0e0ed74da79f058a69414838b..97b42c84c1d29006ce7cbd190015da2b42b28220 100644 (file)
@@ -1995,13 +1995,13 @@ int parse_class_declaration (cp, cfile, group, type)
 {
        const char *val;
        enum dhcp_token token;
-       struct class *class = (struct class *)0, *pc = (struct class *)0;
+       struct class *class = NULL, *pc = NULL;
        int declaration = 0;
        int lose = 0;
        struct data_string data;
        char *name;
        const char *tname;
-       struct executable_statement *stmt = (struct executable_statement *)0;
+       struct executable_statement *stmt = NULL;
        int new = 1;
        isc_result_t status = ISC_R_FAILURE;
        int matchedonce = 0;
@@ -2014,7 +2014,7 @@ int parse_class_declaration (cp, cfile, group, type)
                          "for DHCPv6.");
        }
 
-       token = next_token (&val, (unsigned *)0, cfile);
+       token = next_token (&val, NULL, cfile);
        if (token != STRING) {
                parse_warn (cfile, "Expecting class name");
                skip_to_semi (cfile);
@@ -2047,7 +2047,7 @@ int parse_class_declaration (cp, cfile, group, type)
           the vendor class or user class. */
        if ((type == CLASS_TYPE_VENDOR) || (type == CLASS_TYPE_USER)) {
                data.len = strlen (val);
-               data.buffer = (struct buffer *)0;
+               data.buffer = NULL;
                if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
                        log_fatal ("no memory for class name.");
                data.data = &data.buffer -> data [0];
@@ -2057,7 +2057,7 @@ int parse_class_declaration (cp, cfile, group, type)
        } else if (type == CLASS_TYPE_CLASS) {
                tname = val;
        } else {
-               tname = (const char *)0;
+               tname = NULL;
        }
 
        if (tname) {
@@ -2066,14 +2066,15 @@ int parse_class_declaration (cp, cfile, group, type)
                        log_fatal ("No memory for class name %s.", tname);
                strcpy (name, val);
        } else
-               name = (char *)0;
+               name = NULL;
 
        /* If this is a straight subclass, parse the hash string. */
        if (type == CLASS_TYPE_SUBCLASS) {
-               token = peek_token (&val, (unsigned *)0, cfile);
+               token = peek_token (&val, NULL, cfile);
                if (token == STRING) {
                        skip_token(&val, &data.len, cfile);
-                       data.buffer = (struct buffer *)0;
+                       data.buffer = NULL;
+
                        if (!buffer_allocate (&data.buffer,
                                              data.len + 1, MDL)) {
                                if (pc)
@@ -2109,7 +2110,11 @@ int parse_class_declaration (cp, cfile, group, type)
        /* If we didn't find an existing class, allocate a new one. */
        if (!class) {
                /* Allocate the class structure... */
-               status = class_allocate (&class, MDL);
+               if (type == CLASS_TYPE_SUBCLASS) {
+                       status = subclass_allocate (&class, MDL);
+               } else {
+                       status = class_allocate (&class, MDL);
+               }
                if (pc) {
                        group_reference (&class -> group, pc -> group, MDL);
                        class_reference (&class -> superclass, pc, MDL);
@@ -2143,7 +2148,7 @@ int parse_class_declaration (cp, cfile, group, type)
                   statement that causes the vendor or user class ID to
                   be sent back in the reply. */
                if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
-                       stmt = (struct executable_statement *)0;
+                       stmt = NULL;
                        if (!executable_statement_allocate (&stmt, MDL))
                                log_fatal ("no memory for class statement.");
                        stmt -> op = supersede_option_statement;
@@ -2172,9 +2177,10 @@ int parse_class_declaration (cp, cfile, group, type)
 
        /* Spawned classes don't have to have their own settings. */
        if (class -> superclass) {
-               token = peek_token (&val, (unsigned *)0, cfile);
+               token = peek_token (&val, NULL, cfile);
                if (token == SEMI) {
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
+
                        if (cp)
                                status = class_reference (cp, class, MDL);
                        class_dereference (&class, MDL);
@@ -2196,23 +2202,23 @@ int parse_class_declaration (cp, cfile, group, type)
        }
 
        do {
-               token = peek_token (&val, (unsigned *)0, cfile);
+               token = peek_token (&val, NULL, cfile);
                if (token == RBRACE) {
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
                        break;
                } else if (token == END_OF_FILE) {
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
                        parse_warn (cfile, "unexpected end of file");
                        break;
                } else if (token == DYNAMIC) {
                        class->flags |= CLASS_DECL_DYNAMIC;
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
                        if (!parse_semi (cfile))
                                break;
                        continue;
                } else if (token == TOKEN_DELETED) {
                        class->flags |= CLASS_DECL_DELETED;
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
                        if (!parse_semi (cfile))
                                break;
                        continue;
@@ -2223,11 +2229,11 @@ int parse_class_declaration (cp, cfile, group, type)
                                skip_to_semi (cfile);
                                break;
                        }
-                       skip_token(&val, (unsigned *)0, cfile);
-                       token = peek_token (&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
+                       token = peek_token (&val, NULL, cfile);
                        if (token != IF)
                                goto submatch;
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
                        if (matchedonce) {
                                parse_warn(cfile, "A class may only have "
                                                  "one 'match if' clause.");
@@ -2252,7 +2258,7 @@ int parse_class_declaration (cp, cfile, group, type)
                                parse_semi (cfile);
                        }
                } else if (token == SPAWN) {
-                       skip_token(&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
                        if (pc) {
                                parse_warn (cfile,
                                            "invalid spawn in subclass.");
@@ -2260,7 +2266,7 @@ int parse_class_declaration (cp, cfile, group, type)
                                break;
                        }
                        class -> spawning = 1;
-                       token = next_token (&val, (unsigned *)0, cfile);
+                       token = next_token (&val, NULL, cfile);
                        if (token != WITH) {
                                parse_warn (cfile,
                                            "expecting with after spawn");
@@ -2293,15 +2299,15 @@ int parse_class_declaration (cp, cfile, group, type)
                                parse_semi (cfile);
                        }
                } else if (token == LEASE) {
-                       skip_token(&val, (unsigned *)0, cfile);
-                       token = next_token (&val, (unsigned *)0, cfile);
+                       skip_token(&val, NULL, cfile);
+                       token = next_token (&val, NULL, cfile);
                        if (token != LIMIT) {
                                parse_warn (cfile, "expecting \"limit\"");
                                if (token != SEMI)
                                        skip_to_semi (cfile);
                                break;
                        }
-                       token = next_token (&val, (unsigned *)0, cfile);
+                       token = next_token (&val, NULL, cfile);
                        if (token != NUMBER) {
                                parse_warn (cfile, "expecting a number");
                                if (token != SEMI)
@@ -2323,8 +2329,7 @@ int parse_class_declaration (cp, cfile, group, type)
                        parse_semi (cfile);
                } else {
                        declaration = parse_statement (cfile, class -> group,
-                                                      CLASS_DECL,
-                                                      (struct host_decl *)0,
+                                                      CLASS_DECL, NULL,
                                                       declaration);
                }
        } while (1);
index 18378b3b005d7602d3d9672fd05459ae856fc2ba..4793f4ac027ac661e79177c154c6fb8905224d74 100644 (file)
@@ -3,7 +3,7 @@
    Server-specific in-memory database support. */
 
 /*
- * Copyright (c) 2011-2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2011-2013 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
@@ -443,9 +443,18 @@ isc_result_t delete_class (cp, commit)
                        return ISC_R_IOERROR;
        }
        
-       unlink_class(&cp);              /* remove from collections */
+       /*
+        * If this is a subclass remove it from the class's hash table
+        */
+       if (cp->superclass) {
+               class_hash_delete(cp->superclass->hash, 
+                                 (const char *)cp->hash_string.data,
+                                 cp->hash_string.len,
+                                 MDL);
+       }
 
-       class_dereference(&cp, MDL);
+       /* remove from collections */
+       unlink_class(&cp);
 
        return ISC_R_SUCCESS;
 }
index 9a44fc0b84d1ed71d0fdf48d7cfc85687938aa46..3ecf6a776cdf7a901b226321b931dc24f9702447 100644 (file)
@@ -3,7 +3,8 @@
    OMAPI object interfaces for the DHCP server. */
 
 /*
- * Copyright (c) 2004-2009,2012,2013 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2012-2013 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1999-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -68,7 +69,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_lease_destroy,
                                             dhcp_lease_signal_handler,
                                             dhcp_lease_stuff_values,
-                                            dhcp_lease_lookup, 
+                                            dhcp_lease_lookup,
                                             dhcp_lease_create,
                                             dhcp_lease_remove,
 #if defined (COMPACT_LEASES)
@@ -91,7 +92,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_class_destroy,
                                             dhcp_class_signal_handler,
                                             dhcp_class_stuff_values,
-                                            dhcp_class_lookup, 
+                                            dhcp_class_lookup,
                                             dhcp_class_create,
                                             dhcp_class_remove, 0, 0, 0,
                                             sizeof (struct class), 0,
@@ -107,7 +108,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_class_destroy,
                                             dhcp_subclass_signal_handler,
                                             dhcp_subclass_stuff_values,
-                                            dhcp_subclass_lookup, 
+                                            dhcp_subclass_lookup,
                                             dhcp_subclass_create,
                                             dhcp_subclass_remove, 0, 0, 0,
                                             sizeof (struct class), 0, RC_MISC);
@@ -122,7 +123,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_pool_destroy,
                                             dhcp_pool_signal_handler,
                                             dhcp_pool_stuff_values,
-                                            dhcp_pool_lookup, 
+                                            dhcp_pool_lookup,
                                             dhcp_pool_create,
                                             dhcp_pool_remove, 0, 0, 0,
                                             sizeof (struct pool), 0, RC_MISC);
@@ -138,7 +139,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_host_destroy,
                                             dhcp_host_signal_handler,
                                             dhcp_host_stuff_values,
-                                            dhcp_host_lookup, 
+                                            dhcp_host_lookup,
                                             dhcp_host_create,
                                             dhcp_host_remove, 0, 0, 0,
                                             sizeof (struct host_decl),
@@ -156,7 +157,7 @@ void dhcp_db_objects_setup ()
                                             dhcp_failover_state_destroy,
                                             dhcp_failover_state_signal,
                                             dhcp_failover_state_stuff,
-                                            dhcp_failover_state_lookup, 
+                                            dhcp_failover_state_lookup,
                                             dhcp_failover_state_create,
                                             dhcp_failover_state_remove,
                                             0, 0, 0,
@@ -220,7 +221,7 @@ isc_result_t dhcp_lease_set_value  (omapi_object_t *h,
            status = omapi_get_int_value (&bar, value);
            if (status != ISC_R_SUCCESS)
                return status;
-           
+
            if (bar < 1 || bar > FTS_LAST)
                return DHCP_R_INVALIDARG;
            nls = binding_state_names [bar - 1];
@@ -229,7 +230,7 @@ isc_result_t dhcp_lease_set_value  (omapi_object_t *h,
                ols = binding_state_names [lease -> binding_state - 1];
            else
                ols = "unknown state";
-           
+
            if (lease -> binding_state != bar) {
                lease -> next_binding_state = bar;
                if (supersede_lease (lease, 0, 1, 1, 1)) {
@@ -312,7 +313,7 @@ isc_result_t dhcp_lease_set_value  (omapi_object_t *h,
                if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
                        return status;
        }
-                         
+
        if (!lease -> scope) {
                if (!binding_scope_allocate (&lease -> scope, MDL))
                        return ISC_R_NOMEMORY;
@@ -514,15 +515,10 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
 
        /* Write out all the values. */
 
-       status = omapi_connection_put_name (c, "state");
+       status = omapi_connection_put_named_uint32(c, "state",
+                                                  lease->binding_state);
        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, lease -> binding_state);
-       if (status != ISC_R_SUCCESS)
-               return status;
+               return (status);
 
        status = omapi_connection_put_name (c, "ip-address");
        if (status != ISC_R_SUCCESS)
@@ -615,16 +611,10 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
                if (status != ISC_R_SUCCESS)
                        return status;
 
-               status = omapi_connection_put_name (c, "hardware-type");
+               status = omapi_connection_put_named_uint32(c, "hardware-type",
+                                               lease->hardware_addr.hbuf[0]);
                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, lease -> hardware_addr.hbuf [0]);
-               if (status != ISC_R_SUCCESS)
-                       return status;
+                       return (status);
        }
 
        /* TIME values may be 64-bit, depending on system architecture.
@@ -638,68 +628,32 @@ isc_result_t dhcp_lease_stuff_values (omapi_object_t *c,
         * 32-bit, code.
         */
        bouncer = (u_int32_t)lease->ends;
-       status = omapi_connection_put_name(c, "ends");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, sizeof(bouncer));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, bouncer);
+       status = omapi_connection_put_named_uint32(c, "ends", bouncer);
        if (status != ISC_R_SUCCESS)
-               return status;
+               return (status);
 
        bouncer = (u_int32_t)lease->starts;
-       status = omapi_connection_put_name(c, "starts");
+       status = omapi_connection_put_named_uint32(c, "starts", bouncer);
        if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, sizeof(bouncer));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, bouncer);
-       if (status != ISC_R_SUCCESS)
-               return status;
+               return (status);
 
        bouncer = (u_int32_t)lease->tstp;
-       status = omapi_connection_put_name(c, "tstp");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, sizeof(bouncer));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, bouncer);
+       status = omapi_connection_put_named_uint32(c, "tstp", bouncer);
        if (status != ISC_R_SUCCESS)
-               return status;
+               return (status);
 
        bouncer = (u_int32_t)lease->tsfp;
-       status = omapi_connection_put_name(c, "tsfp");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, sizeof(bouncer));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, bouncer);
+       status = omapi_connection_put_named_uint32(c, "tsfp", bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
        bouncer = (u_int32_t)lease->atsfp;
-       status = omapi_connection_put_name(c, "atsfp");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, sizeof(bouncer));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, bouncer);
+       status = omapi_connection_put_named_uint32(c, "atsfp", bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
        bouncer = (u_int32_t)lease->cltt;
-       status = omapi_connection_put_name(c, "cltt");
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, sizeof(bouncer));
-       if (status != ISC_R_SUCCESS)
-               return status;
-       status = omapi_connection_put_uint32(c, bouncer);
+       status = omapi_connection_put_named_uint32(c, "cltt", bouncer);
        if (status != ISC_R_SUCCESS)
                return status;
 
@@ -794,7 +748,7 @@ isc_result_t dhcp_lease_lookup (omapi_object_t **lp,
                                     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);
@@ -921,13 +875,13 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                return DHCP_R_INVALIDARG;
        host = (struct host_decl *)h;
 
-       /* XXX For now, we can only set these values on new host objects. 
+       /* XXX For now, we can only set these values on new host objects.
           XXX Soon, we need to be able to update host objects. */
        if (!omapi_ds_strcmp (name, "name")) {
                if (host -> name)
                        return ISC_R_EXISTS;
                if (value && (value -> type == omapi_datatype_data ||
-                             value -> type == omapi_datatype_string)) {
+                             value -> type == omapi_datatype_string)) {
                        host -> name = dmalloc (value -> u.buffer.len + 1,
                                                MDL);
                        if (!host -> name)
@@ -943,7 +897,7 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
 
        if (!omapi_ds_strcmp (name, "group")) {
                if (value && (value -> type == omapi_datatype_data ||
-                             value -> type == omapi_datatype_string)) {
+                             value -> type == omapi_datatype_string)) {
                        struct group_object *group;
                        group = (struct group_object *)0;
                        group_hash_lookup (&group, group_name_hash,
@@ -969,7 +923,7 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                if (host -> interface.hlen)
                        return ISC_R_EXISTS;
                if (value && (value -> type == omapi_datatype_data ||
-                             value -> type == omapi_datatype_string)) {
+                             value -> type == omapi_datatype_string)) {
                        if (value -> u.buffer.len >
                            (sizeof host -> interface.hbuf) - 1)
                                return DHCP_R_INVALIDARG;
@@ -1005,7 +959,7 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                if (host -> client_identifier.data)
                        return ISC_R_EXISTS;
                if (value && (value -> type == omapi_datatype_data ||
-                             value -> type == omapi_datatype_string)) {
+                             value -> type == omapi_datatype_string)) {
                    if (!buffer_allocate (&host -> client_identifier.buffer,
                                          value -> u.buffer.len, MDL))
                            return ISC_R_NOMEMORY;
@@ -1099,7 +1053,7 @@ isc_result_t dhcp_host_set_value  (omapi_object_t *h,
                if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
                        return status;
        }
-                         
+
        return DHCP_R_UNKNOWNATTRIBUTE;
 }
 
@@ -1327,14 +1281,8 @@ isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
                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.hbuf [0]));
+               status = omapi_connection_put_named_uint32(c, "hardware-type",
+                                                          host->interface.hbuf[0]);
                if (status != ISC_R_SUCCESS)
                        return status;
        }
@@ -1458,7 +1406,7 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
                host = (struct host_decl *)0;
                host_hash_lookup (&host, host_hw_addr_hash, haddr, len, MDL);
                dfree (haddr, MDL);
-                       
+
                if (*lp && *lp != (omapi_object_t *)host) {
                        omapi_object_dereference (lp, MDL);
                        if (host)
@@ -1500,7 +1448,7 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
                        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)
@@ -1531,7 +1479,7 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
                                  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)
@@ -1540,7 +1488,7 @@ isc_result_t dhcp_host_lookup (omapi_object_t **lp,
                } else if (!host || (host -> flags & HOST_DECL_DELETED)) {
                        if (host)
                            host_dereference (&host, MDL);
-                       return ISC_R_NOTFOUND;  
+                       return ISC_R_NOTFOUND;
                } else if (!*lp) {
                        /* XXX fix so that hash lookup itself creates
                           XXX the reference. */
@@ -1608,7 +1556,7 @@ isc_result_t dhcp_pool_set_value  (omapi_object_t *h,
                if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
                        return status;
        }
-                         
+
        return DHCP_R_UNKNOWNATTRIBUTE;
 }
 
@@ -1711,23 +1659,46 @@ isc_result_t dhcp_pool_stuff_values (omapi_object_t *c,
                                     omapi_object_t *id,
                                     omapi_object_t *h)
 {
-       /* h should point to (struct pool *) */
+       struct pool *pool;
        isc_result_t status;
 
-       if (h -> type != dhcp_type_pool)
-               return DHCP_R_INVALIDARG;
+       if (h->type != dhcp_type_pool)
+               return (DHCP_R_INVALIDARG);
+       pool = (struct pool *)h;
 
-       /* Can't stuff pool values yet. */
+       /*
+        * I don't think we can actually find a pool yet
+        * but include the output of interesting values
+        * for when we do
+        */
+       status = omapi_connection_put_named_uint32(c, "lease-count",
+                                                  ((u_int32_t)
+                                                   pool->lease_count));
+       if (status != ISC_R_SUCCESS)
+               return (status);
+
+       status = omapi_connection_put_named_uint32(c, "free-leases",
+                                                  ((u_int32_t)
+                                                   pool->free_leases));
+       if (status != ISC_R_SUCCESS)
+               return (status);
+
+       status = omapi_connection_put_named_uint32(c, "backup-leases", 
+                                                  ((u_int32_t)
+                                                   pool->backup_leases));
+       if (status != ISC_R_SUCCESS)
+               return (status);
+       /* we could add time stamps but lets wait on those */
 
        /* 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 (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 (status);
        }
 
-       return ISC_R_SUCCESS;
+       return (ISC_R_SUCCESS);
 }
 
 isc_result_t dhcp_pool_lookup (omapi_object_t **lp,
@@ -1789,10 +1760,25 @@ class_set_value (omapi_object_t *h,
 
                        if (class->superclass != NULL)
                                class_dereference(&class->superclass, MDL);
-
                        class_reference(&class->superclass, superclass, MDL);
-               } else if (value -> type == omapi_datatype_data ||
-                          value -> type == omapi_datatype_string) {
+
+                       if (class->group != NULL)
+                               group_dereference(&class->group, MDL);
+                       group_reference(&class->group, superclass->group, MDL);
+
+                       class->lease_limit = superclass->lease_limit;
+                       if (class->lease_limit != 0) {
+                               class->billed_leases =
+                                       dmalloc(class->lease_limit *
+                                               sizeof(struct lease *),
+                                               MDL);
+                               if (class->billed_leases == NULL) {
+                                       return ISC_R_NOMEMORY;
+                               }
+                       }
+
+               } else if (value->type == omapi_datatype_data ||
+                          value->type == omapi_datatype_string) {
                        class->name = dmalloc(value->u.buffer.len + 1, MDL);
                        if (!class->name)
                                return ISC_R_NOMEMORY;
@@ -1883,7 +1869,7 @@ class_set_value (omapi_object_t *h,
                } else
                        return DHCP_R_INVALIDARG;
 
-               /* 
+               /*
                 * Currently no way to get here, if we update the above
                 * code so that we do get here this return needs to be
                 * uncommented.
@@ -1946,10 +1932,8 @@ isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
 
        if (h -> type != dhcp_type_class && h -> type != dhcp_type_subclass)
                return DHCP_R_INVALIDARG;
-
-#if defined (DEBUG_MEMORY_LEAKAGE) || \
-               defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
        struct class *class = (struct class *)h;
+
        if (class -> nic)
                class_dereference (&class -> nic, file, line);
        if (class -> superclass)
@@ -1986,7 +1970,6 @@ isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
                                                  file, line);
        if (class -> superclass)
                class_dereference (&class -> superclass, file, line);
-#endif
 
        return ISC_R_SUCCESS;
 }
@@ -2000,46 +1983,45 @@ class_signal_handler(omapi_object_t *h,
        int updatep = 0;
        int issubclass;
 
-       issubclass = (h -> type == dhcp_type_subclass);
+       issubclass = (h->type == dhcp_type_subclass);
 
        if (!strcmp (name, "updated")) {
-               
+
                if (!issubclass) {
-                       if (class -> name == 0 || strlen(class -> name) == 0) {
+                       if (class->name == 0 || strlen(class->name) == 0) {
                                return DHCP_R_INVALIDARG;
                        }
                } else {
-                       if (class -> superclass == 0) {
+                       if (class->superclass == 0) {
                                return DHCP_R_INVALIDARG; /* didn't give name */
                        }
 
-                       if (class -> hash_string.data == NULL) {
+                       if (class->hash_string.data == NULL) {
                                return DHCP_R_INVALIDARG;
                        }
                }
 
 
                if (issubclass) {
-                       if (!class -> superclass -> hash)
+                       if (!class->superclass->hash)
                                class_new_hash(&class->superclass->hash,
                                               SCLASS_HASH_SIZE, MDL);
 
-                       add_hash (class -> superclass -> hash,
-                                 class -> hash_string.data,
-                                 class -> hash_string.len,
-                                 (void *)class, MDL);
+                       class_hash_add(class->superclass->hash,
+                                      (const char *)class->hash_string.data,
+                                      class->hash_string.len,
+                                      (void *)class, MDL);
                }
-                       
-               
+
 #ifdef DEBUG_OMAPI
                if (issubclass) {
                        log_debug ("OMAPI added subclass %s",
-                                  class -> superclass -> name);
+                                  class->superclass->name);
                } else {
-                       log_debug ("OMAPI added class %s", class -> name);
+                       log_debug ("OMAPI added class %s", class->name);
                }
 #endif
-               
+
                status = enter_class (class, 1, 1);
                if (status != ISC_R_SUCCESS)
                        return status;
@@ -2047,9 +2029,9 @@ class_signal_handler(omapi_object_t *h,
        }
 
        /* Try to find some inner object that can take the value. */
-       if (h -> inner && h -> inner -> type -> signal_handler) {
-               status = ((*(h -> inner -> type -> signal_handler))
-                         (h -> inner, name, ap));
+       if (h->inner && h->inner->type->signal_handler) {
+               status = ((*(h->inner->type->signal_handler))
+                         (h->inner, name, ap));
                if (status == ISC_R_SUCCESS)
                        return status;
        }
@@ -2070,108 +2052,138 @@ isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
        return class_signal_handler(h, name, ap);
 }
 
-isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
-                                     omapi_object_t *id,
-                                     omapi_object_t *h)
+
+/*
+ * Routine to put out generic class & subclass information
+ */
+isc_result_t class_stuff_values (omapi_object_t *c,
+                                omapi_object_t *id,
+                                omapi_object_t *h)
 {
-       /* h should point to (struct class *) */
+       struct class *class;
        isc_result_t status;
 
-       if (h -> type != dhcp_type_class)
-               return DHCP_R_INVALIDARG;
+       class = (struct class *)h;
 
-       /* Can't stuff class values yet. */
+       status = omapi_connection_put_named_uint32(c, "lease-limit",
+                                                  ((u_int32_t)
+                                                   class->lease_limit));
+       if (status != ISC_R_SUCCESS)
+               return (status);
+
+       status = omapi_connection_put_named_uint32(c, "leases-used",
+                                                  ((u_int32_t)
+                                                   class->leases_consumed));
+       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 (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 (status);
        }
 
-       return ISC_R_SUCCESS;
+       return (ISC_R_SUCCESS);
+}
+
+
+isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
+                                     omapi_object_t *id,
+                                     omapi_object_t *h)
+{
+       if (h->type != dhcp_type_class)
+               return (DHCP_R_INVALIDARG);
+
+       /* add any class specific items here */
+
+       return (class_stuff_values(c, id, h));
 }
 
 static isc_result_t class_lookup (omapi_object_t **lp,
                                  omapi_object_t *id, omapi_object_t *ref,
                                  omapi_object_type_t *typewanted)
 {
-       omapi_value_t *nv = (omapi_value_t *)0;
-       omapi_value_t *hv = (omapi_value_t *)0;
+       omapi_value_t *nv = NULL;
+       omapi_value_t *hv = NULL;
        isc_result_t status;
        struct class *class = 0;
        struct class *subclass = 0;
 
        *lp = NULL;
-       
+
+       if (ref == NULL)
+               return (DHCP_R_NOKEYS);
+
        /* see if we have a name */
-       status = omapi_get_value_str (ref, id, "name", &nv);
+       status = omapi_get_value_str(ref, id, "name", &nv);
        if (status == ISC_R_SUCCESS) {
-               char *name = dmalloc(nv -> value -> u.buffer.len + 1, MDL);
+               char *name = dmalloc(nv->value->u.buffer.len + 1, MDL);
                memcpy (name,
-                       nv -> value -> u.buffer.value,
-                       nv -> value -> u.buffer.len);
+                       nv->value->u.buffer.value,
+                       nv->value->u.buffer.len);
 
-               omapi_value_dereference (&nv, MDL);
+               omapi_value_dereference(&nv, MDL);
 
                find_class(&class, name, MDL);
 
                dfree(name, MDL);
-               
+
                if (class == NULL) {
-                       return ISC_R_NOTFOUND;
+                       return (ISC_R_NOTFOUND);
                }
 
                if (typewanted == dhcp_type_subclass) {
-                       status = omapi_get_value_str (ref, id,
-                                                     "hashstring", &hv);
+                       status = omapi_get_value_str(ref, id,
+                                                    "hashstring", &hv);
                        if (status != ISC_R_SUCCESS) {
                                class_dereference(&class, MDL);
-                               return DHCP_R_NOKEYS;
+                               return (DHCP_R_NOKEYS);
                        }
 
-                       if (hv -> value -> type != omapi_datatype_data &&
-                           hv -> value -> type != omapi_datatype_string) {
+                       if (hv->value->type != omapi_datatype_data &&
+                           hv->value->type != omapi_datatype_string) {
                                class_dereference(&class, MDL);
-                               omapi_value_dereference (&hv, MDL);
-                               return DHCP_R_NOKEYS;
+                               omapi_value_dereference(&hv, MDL);
+                               return (DHCP_R_NOKEYS);
                        }
-                       
-                       class_hash_lookup (&subclass, class -> hash,
-                                          (const char *)
-                                          hv -> value -> u.buffer.value,
-                                          hv -> value -> u.buffer.len, MDL);
-                       
-                       omapi_value_dereference (&hv, MDL);
+
+                       class_hash_lookup(&subclass, class->hash,
+                                         (const char *)
+                                         hv->value->u.buffer.value,
+                                         hv->value->u.buffer.len, MDL);
+
+                       omapi_value_dereference(&hv, MDL);
 
                        class_dereference(&class, MDL);
-                       
+
                        if (subclass == NULL) {
-                               return ISC_R_NOTFOUND;
+                               return (ISC_R_NOTFOUND);
                        }
 
                        class_reference(&class, subclass, MDL);
                        class_dereference(&subclass, MDL);
                }
-               
-                       
+
                /* Don't return the object if the type is wrong. */
-               if (class -> type != typewanted) {
-                       class_dereference (&class, MDL);
-                       return DHCP_R_INVALIDARG;
+               if (class->type != typewanted) {
+                       class_dereference(&class, MDL);
+                       return (DHCP_R_INVALIDARG);
                }
-               
-               if (class -> flags & CLASS_DECL_DELETED) {
-                       class_dereference (&class, MDL);
+
+               if (class->flags & CLASS_DECL_DELETED) {
+                       class_dereference(&class, MDL);
+                       return (ISC_R_NOTFOUND);
                }
 
                omapi_object_reference(lp, (omapi_object_t *)class, MDL);
-               
-               return ISC_R_SUCCESS;
+               class_dereference(&class, MDL);
+
+               return (ISC_R_SUCCESS);
        }
 
-       return DHCP_R_NOKEYS;
+       return (DHCP_R_NOKEYS);
 }
 
 
@@ -2186,16 +2198,16 @@ isc_result_t dhcp_class_create (omapi_object_t **lp,
 {
        struct class *cp = 0;
        isc_result_t status;
-       
+
        status = class_allocate(&cp, MDL);
        if (status != ISC_R_SUCCESS)
-               return status;
-       
-       group_reference (&cp -> group, root_group, MDL);
-       cp -> flags = CLASS_DECL_DYNAMIC;
-       status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
-       class_dereference (&cp, MDL);
-       return status;
+               return (status);
+
+       clone_group(&cp->group, root_group, MDL);
+       cp->flags = CLASS_DECL_DYNAMIC;
+       status = omapi_object_reference(lp, (omapi_object_t *)cp, MDL);
+       class_dereference(&cp, MDL);
+       return (status);
 }
 
 isc_result_t dhcp_class_remove (omapi_object_t *lp,
@@ -2209,7 +2221,7 @@ isc_result_t dhcp_class_remove (omapi_object_t *lp,
 #ifdef DEBUG_OMAPI
        log_debug ("OMAPI delete class %s", cp -> name);
 #endif
-       
+
        delete_class (cp, 1);
        return ISC_R_SUCCESS;
 }
@@ -2238,7 +2250,7 @@ isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
        subclass = (struct class *)h;
        if (subclass -> name != 0)
                return DHCP_R_INVALIDARG;
-       
+
        /* XXXJAB No values to get yet. */
 
        /* Try to find some inner object that can provide the value. */
@@ -2266,26 +2278,16 @@ isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
                                         omapi_object_t *h)
 {
        struct class *subclass;
-       isc_result_t status;
 
-       if (h -> type != dhcp_type_class)
-               return DHCP_R_INVALIDARG;
+       if (h->type != dhcp_type_subclass)
+               return (DHCP_R_INVALIDARG);
        subclass = (struct class *)h;
-       if (subclass -> name != 0)
-               return DHCP_R_INVALIDARG;
-       
-
-       /* Can't stuff subclass values yet. */
+       if (subclass->name != 0)
+               return (DHCP_R_INVALIDARG);
 
-       /* 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;
-       }
+       /* add any subclass specific items here */
 
-       return ISC_R_SUCCESS;
+       return (class_stuff_values(c, id, h));
 }
 
 isc_result_t dhcp_subclass_lookup (omapi_object_t **lp,
@@ -2303,26 +2305,13 @@ isc_result_t dhcp_subclass_create (omapi_object_t **lp,
        struct class *cp = 0;
        isc_result_t status;
 
-/*
- * XXX
- * NOTE: subclasses and classes have the same internal type, which makes it
- * difficult to tell them apart. Specifically, in this function we need to
- * create a class object (because there is no such thing as a subclass
- * object), but one field of the class object is the type (which has the
- * value dhcp_type_class), and it is from here that all the other omapi
- * functions are accessed. So, even though there's a whole suite of
- * subclass functions registered, they won't get used. Now we could change
- * the type pointer after creating the class object, but I'm not certain
- * that won't break something else.
- */
-       
        status = subclass_allocate(&cp, MDL);
        if (status != ISC_R_SUCCESS)
                return status;
-       group_reference (&cp -> group, root_group, MDL);
+       group_reference (&cp->group, root_group, MDL);
+
+       cp->flags = CLASS_DECL_DYNAMIC;
 
-       cp -> flags = CLASS_DECL_DYNAMIC;
-       
        status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
        subclass_dereference (&cp, MDL);
        return status;
@@ -2331,13 +2320,6 @@ isc_result_t dhcp_subclass_create (omapi_object_t **lp,
 isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
                                   omapi_object_t *id)
 {
-#if 1
-
-       log_fatal("calling dhcp_subclass_set_value");
-       /* this should never be called see dhcp_subclass_create for why */
-
-#else  
-       
        struct class *cp;
        if (lp -> type != dhcp_type_subclass)
                return DHCP_R_INVALIDARG;
@@ -2346,11 +2328,9 @@ isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
 #ifdef DEBUG_OMAPI
        log_debug ("OMAPI delete subclass %s", cp -> name);
 #endif
-       
+
        delete_class (cp, 1);
 
-#endif
-       
        return ISC_R_SUCCESS;
 }
 
@@ -2370,7 +2350,7 @@ isc_result_t binding_scope_set_value (struct binding_scope *scope, int createp,
        if (!bp && !createp) {
                dfree (nname, MDL);
                return DHCP_R_UNKNOWNATTRIBUTE;
-       } 
+       }
        if (!value) {
                dfree (nname, MDL);
                if (!bp)
@@ -2492,7 +2472,7 @@ isc_result_t binding_scope_get_value (omapi_value_t **value,
                omapi_typed_data_dereference (&td, MDL);
                return status;
        }
-       
+
        omapi_data_string_reference (&(*value) -> name, name, MDL);
        omapi_typed_data_reference (&(*value) -> value, td, MDL);
        omapi_typed_data_dereference (&td, MDL);