]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
OMAPI class and subclass support.
authorJames Brister <source@isc.org>
Fri, 22 Jun 2001 16:47:20 +0000 (16:47 +0000)
committerJames Brister <source@isc.org>
Fri, 22 Jun 2001 16:47:20 +0000 (16:47 +0000)
includes/dhcpd.h
server/class.c
server/confpars.c
server/db.c
server/mdb.c
server/omapi.c
server/salloc.c

index 2c34629e7fd4f49cee4d93d6b454a6036f5c0894..d7c56a25996573f7f94e86d96f15b5deeab836c2 100644 (file)
@@ -572,7 +572,7 @@ struct class {
        OMAPI_OBJECT_PREAMBLE;
        struct class *nic;      /* Next in collection. */
        struct class *superclass;       /* Set for spawned classes only. */
-       const char *name;               /* Not set for spawned classes. */
+       char *name;             /* Not set for spawned classes. */
 
        /* A class may be configured to permit a limited number of leases. */
        int lease_limit;
@@ -597,8 +597,16 @@ struct class {
        
        struct group *group;
 
+
        /* Statements to execute if class matches. */
        struct executable_statement *statements;
+
+#define CLASS_DECL_DELETED     1
+#define CLASS_DECL_DYNAMIC     2
+#define CLASS_DECL_STATIC      4
+#define CLASS_DECL_SUBCLASS    8
+       
+       int flags;
 };
 
 /* DHCP client lease structure... */
@@ -1340,6 +1348,7 @@ int write_group PROTO ((struct group_object *));
 struct lease *new_leases PROTO ((unsigned, const char *, int));
 OMAPI_OBJECT_ALLOC_DECL (lease, struct lease, dhcp_type_lease)
 OMAPI_OBJECT_ALLOC_DECL (class, struct class, dhcp_type_class)
+OMAPI_OBJECT_ALLOC_DECL (subclass, struct class, dhcp_type_subclass)
 OMAPI_OBJECT_ALLOC_DECL (pool, struct pool, dhcp_type_pool)
 OMAPI_OBJECT_ALLOC_DECL (host, struct host_decl, dhcp_type_host)
 
@@ -1985,6 +1994,7 @@ void classify_client PROTO ((struct packet *));
 int check_collection PROTO ((struct packet *, struct lease *,
                             struct collection *));
 void classify PROTO ((struct packet *, struct class *));
+isc_result_t unlink_class PROTO((struct class **class));
 isc_result_t find_class PROTO ((struct class **, const char *,
                                const char *, int));
 int unbill_class PROTO ((struct lease *, struct class *));
@@ -2086,6 +2096,7 @@ extern int (*dhcp_interface_shutdown_hook) (struct interface_info *);
 extern omapi_object_type_t *dhcp_type_lease;
 extern omapi_object_type_t *dhcp_type_pool;
 extern omapi_object_type_t *dhcp_type_class;
+extern omapi_object_type_t *dhcp_type_subclass;
 
 #if defined (FAILOVER_PROTOCOL)
 extern omapi_object_type_t *dhcp_type_failover_state;
@@ -2275,6 +2286,8 @@ extern struct hash_table *lease_hw_addr_hash;
 
 extern omapi_object_type_t *dhcp_type_host;
 
+isc_result_t enter_class PROTO ((struct class *, int, int));
+isc_result_t delete_class PROTO ((struct class *, int));
 isc_result_t enter_host PROTO ((struct host_decl *, int, int));
 isc_result_t delete_host PROTO ((struct host_decl *, int));
 int find_hosts_by_haddr PROTO ((struct host_decl **, int,
index 5b89bcca84eb583efaff35f44cc3dab690a35d09..2516048368e1dbe2af0e40eb5f2c3b2ab64108a4 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: class.c,v 1.29 2001/04/20 20:39:26 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: class.c,v 1.30 2001/06/22 16:47:13 brister Exp $ Copyright (c) 1998-2000 The Internet Software Consortium.  All rights reserved.\n";
 
 #endif /* not lint */
 
@@ -227,6 +227,29 @@ void classify (packet, class)
                                     packet -> raw -> chaddr));
 }
 
+
+isc_result_t unlink_class(struct class **class) {
+       struct collection *lp;
+       struct class *cp, *pp;
+
+       for (lp = collections; lp; lp = lp -> next) {
+               for (pp = 0, cp = lp -> classes; cp; pp = cp, cp = cp -> nic)
+                       if (cp == *class) {
+                               if (pp == 0) {
+                                       lp->classes = cp->nic;
+                               } else {
+                                       pp->nic = cp->nic;
+                               }
+                               cp->nic = 0;
+                               class_dereference(class, MDL);
+
+                               return ISC_R_SUCCESS;
+                       }
+       }
+       return ISC_R_NOTFOUND;
+}
+
+       
 isc_result_t find_class (struct class **class, const char *name,
                         const char *file, int line)
 {
index 41c916c74bb222fd98e8d8e3ed89e4f34d253c67..970a96809df8c789a0ce7d251556767ed98cea00 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.143 2001/05/02 07:05:52 mellon Exp $ Copyright (c) 1995-2001 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.144 2001/06/22 16:47:14 brister Exp $ Copyright (c) 1995-2001 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -274,6 +274,10 @@ isc_result_t lease_file_subparse (struct parse *cfile)
                        } else
                                parse_warn (cfile,
                                            "possibly corrupt lease file");
+               } else if (token == CLASS) {
+                       parse_class_declaration (0, cfile, root_group, 2);
+               } else if (token == SUBCLASS) {
+                       parse_class_declaration (0, cfile, root_group, 3);
                } else if (token == HOST) {
                        parse_host_declaration (cfile, root_group);
                } else if (token == GROUP) {
@@ -1677,6 +1681,8 @@ int parse_class_declaration (cp, cfile, group, type)
        struct expression *expr;
        int new = 1;
        isc_result_t status;
+       int deleted = 0;
+       int dynamic = 0;
 
        token = next_token (&val, (unsigned *)0, cfile);
        if (token != STRING) {
@@ -1824,7 +1830,7 @@ int parse_class_declaration (cp, cfile, group, type)
                }
 
                /* Save the name, if there is one. */
-               class -> name = name;
+               class -> name = (char *)name;
        }
 
        if (type == 0 || type == 1 || type == 3)
@@ -1862,6 +1868,18 @@ int parse_class_declaration (cp, cfile, group, type)
                        token = next_token (&val, (unsigned *)0, cfile);
                        parse_warn (cfile, "unexpected end of file");
                        break;
+               } else if (token == DYNAMIC) {
+                       dynamic = 1;
+                       token = next_token (&val, (unsigned *)0, cfile);
+                       if (!parse_semi (cfile))
+                               break;
+                       continue;
+               } else if (token == TOKEN_DELETED) {
+                       deleted = 1;
+                       token = next_token (&val, (unsigned *)0, cfile);
+                       if (!parse_semi (cfile))
+                               break;
+                       continue;
                } else if (token == MATCH) {
                        if (pc) {
                                parse_warn (cfile,
@@ -1965,7 +1983,20 @@ int parse_class_declaration (cp, cfile, group, type)
                                                       declaration);
                }
        } while (1);
-       if (type == 2 && new) {
+
+       if (deleted) {
+               struct class *theclass = 0;
+               
+               status = find_class(&theclass, class->name, MDL);
+               if (status == ISC_R_SUCCESS) {
+                       delete_class(theclass, 0);
+                       class_dereference(&theclass, MDL);
+               }
+       } else if (type == 2 && new) {
+               if (dynamic) {
+                       class->flags |= CLASS_DECL_DYNAMIC;
+               }
+               
                if (!collections -> classes)
                        class_reference (&collections -> classes, class, MDL);
                else {
@@ -1976,7 +2007,7 @@ int parse_class_declaration (cp, cfile, group, type)
                        class_reference (&c -> nic, class, MDL);
                }
        }
-       if (cp)
+       if (cp)                         /* should always be 0??? */
                status = class_reference (cp, class, MDL);
        class_dereference (&class, MDL);
        if (pc)
index 72503428292db4609d631c9bb14dd967c9d2e267..474031afaed02a0342507593d987c6cdb8f379f8 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: db.c,v 1.64 2001/05/17 19:04:04 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: db.c,v 1.65 2001/06/22 16:47:16 brister Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -565,11 +565,102 @@ int db_printable_len (s, len)
        return 1;
 }
 
+static int print_hash_string(FILE *fp, struct class *class)
+{
+       int i;
+       int errors;
+       
+       
+       for (i = 0; i < class -> hash_string.len; i++)
+               if (!isascii (class -> hash_string.data [i]) ||
+                   !isprint (class -> hash_string.data [i]))
+                       break;
+
+       if (i == class -> hash_string.len) {
+               errno = 0;
+               fprintf (fp, " \"%.*s\";",
+                        (int)class -> hash_string.len,
+                        class -> hash_string.data);
+               if (errno)
+                       ++errors;
+       } else {
+               errno = 0;
+               fprintf (fp, " %2.2x", class -> hash_string.data [0]);
+               if (errno)
+                       ++errors;
+               for (i = 1; i < class -> hash_string.len; i++) {
+                       errno = 0;
+                       fprintf (fp, ":%2.2x",
+                                class -> hash_string.data [i]);
+                       if (errno)
+                               ++errors;
+               }
+               errno = 0;
+               if (errno)
+                       ++errors;
+       }
+
+       return !errors;
+}
+
+
+       
+
+/* XXXJAB this needs to return non-zero on error. */
 void write_named_billing_class (const char *name, unsigned len,
                                struct class *class)
 {
-       /* XXX billing classes that are modified by OMAPI need
-          XXX to be detected and written out here. */
+       if (class->superclass == 0) {
+               fprintf(db_file, "class \"%s\" {\n", name);
+       } else {
+               fprintf(db_file, "subclass \"%s\"", class->superclass->name);
+               print_hash_string(db_file, class);
+               fprintf(db_file, " {\n");
+       }
+
+       if ((class->flags & CLASS_DECL_DELETED) != 0) {
+               fprintf(db_file, "  deleted;\n");
+       } else {
+               fprintf(db_file, "  dynamic;\n");
+       }
+       
+
+       if (class->lease_limit > 0) {
+               fprintf(db_file, "  lease limit %d;\n", class->lease_limit);
+       }
+
+       if (class->expr != 0) {
+               fprintf(db_file, "  match if ");
+               write_expression(db_file, class->expr, 5, 5, 0);
+       }
+
+       if (class->submatch != 0) {
+               if (class->spawning) {
+                       fprintf(db_file, "  spawn ");
+               } else {
+                       fprintf(db_file, "  match ");
+               }
+       
+               write_expression(db_file, class->submatch, 5, 5, 0);
+       }
+       
+       if (class->statements != 0) {
+               write_statements(db_file, class->statements, 8);
+       }
+
+       /* XXXJAB this isn't right, but classes read in off the leases file
+          don't get the root group assigned to them (due to clone_group()
+          call). */
+       if (class->group != 0 && class->group->authoritative != 0) {
+               write_statements (db_file,
+                                 class -> group -> statements, 8);
+       }
+       
+       fprintf(db_file, "}\n\n");
+
+       if (class -> hash != NULL) {    /* yep. recursive. god help us. */
+               class_hash_foreach (class -> hash, write_named_billing_class);
+       }
 }
 
 void write_billing_classes ()
@@ -608,6 +699,7 @@ int write_billing_class (class)
        if (errno)
                ++errors;
 
+#if 0
        for (i = 0; i < class -> hash_string.len; i++)
                if (!isascii (class -> hash_string.data [i]) ||
                    !isprint (class -> hash_string.data [i]))
@@ -636,6 +728,10 @@ int write_billing_class (class)
                if (errno)
                        ++errors;
        }
+#else
+       print_hash_string(db_file, class);
+       fprintf(db_file, ";");
+#endif
 
        class -> dirty = 0;
        return !errors;
index 0e704814cea9224162be587a714306fd3de03d66..a0e91924a58c11dfb933c3f84af1cef188955a2f 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: mdb.c,v 1.68 2001/05/17 19:04:08 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: mdb.c,v 1.69 2001/06/22 16:47:17 brister Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -59,6 +59,43 @@ struct hash_table *host_name_hash;
 
 omapi_object_type_t *dhcp_type_host;
 
+isc_result_t enter_class(cd, dynamicp, commit)
+       struct class *cd;
+       int dynamicp;
+       int commit;
+{
+       if (!collections -> classes) {
+               class_reference (&collections -> classes, cd, MDL);
+       } else if (cd->name != NULL) {  /* regular class */
+               struct class *c = 0;
+
+               if (find_class(&c, cd->name, MDL) != ISC_R_NOTFOUND) {
+                       class_dereference(&c, MDL);
+                       return ISC_R_EXISTS;
+               }
+               
+               for (c = collections -> classes;
+                    c -> nic; c = c -> nic)
+                       /* nothing */ ;
+               class_reference (&c -> nic, cd, MDL);
+       }
+
+       if (dynamicp && commit) {
+               const char *name = cd->name;
+
+               if (name == NULL) {
+                       name = cd->superclass->name;
+               }
+
+               write_named_billing_class (name, 0, cd);
+               if (!commit_leases ())
+                       return ISC_R_IOERROR;
+       }
+
+       return ISC_R_SUCCESS;
+}
+
+
 isc_result_t enter_host (hd, dynamicp, commit)
        struct host_decl *hd;
        int dynamicp;
@@ -218,6 +255,30 @@ isc_result_t enter_host (hd, dynamicp, commit)
        return ISC_R_SUCCESS;
 }
 
+
+isc_result_t delete_class (cp, commit)
+       struct class *cp;
+       int commit;
+{
+       cp->flags |= CLASS_DECL_DELETED;
+
+       /* do the write first as we won't be leaving it in any data
+          structures, unlike the host objects */
+       
+       if (commit) {
+               write_named_billing_class (cp->name, 0, cp);
+               if (!commit_leases ())
+                       return ISC_R_IOERROR;
+       }
+       
+       unlink_class(&cp);              /* remove from collections */
+
+       class_dereference(&cp, MDL);
+
+       return ISC_R_SUCCESS;
+}
+
+
 isc_result_t delete_host (hd, commit)
        struct host_decl *hd;
        int commit;
@@ -1712,10 +1773,28 @@ void write_leases ()
        struct host_decl *hp;
        struct group_object *gp;
        struct hash_bucket *hb;
+       struct class *cp;
+       struct collection *colp;
        int i;
        int num_written;
        struct lease **lptr [5];
 
+       /* write all the dynamically-created class declarations. */
+       if (collections->classes) {
+               num_written = 0;
+               for (colp = collections ; colp ; colp = colp->next) {
+                       for (cp = colp->classes ; cp ; cp = cp->nic) {
+                               write_named_billing_class(cp->name,
+                                                         0, cp);
+                               ++num_written;
+                       }
+               }
+
+               /* XXXJAB this number doesn't include subclasses... */ 
+               log_info ("Wrote %d class decls to leases file.", num_written);
+       }
+       
+                       
        /* Write all the dynamically-created group declarations. */
        if (group_name_hash) {
            num_written = 0;
index 991377c1c211b53d172ed90fd1bbd7d5dd46e938..00ac7d718ced948ba3ba1c7734a354f6cc3eea60 100644 (file)
@@ -50,7 +50,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: omapi.c,v 1.47 2001/05/17 19:04:09 mellon Exp $ Copyright (c) 1999-2001 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: omapi.c,v 1.48 2001/06/22 16:47:18 brister Exp $ Copyright (c) 1999-2001 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1196,7 +1196,7 @@ isc_result_t dhcp_host_stuff_values (omapi_object_t *c,
 }
 
 isc_result_t dhcp_host_lookup (omapi_object_t **lp,
-                               omapi_object_t *id, omapi_object_t *ref)
+                              omapi_object_t *id, omapi_object_t *ref)
 {
        omapi_value_t *tv = (omapi_value_t *)0;
        isc_result_t status;
@@ -1571,20 +1571,132 @@ isc_result_t dhcp_pool_remove (omapi_object_t *lp,
        return ISC_R_NOTIMPLEMENTED;
 }
 
-isc_result_t dhcp_class_set_value  (omapi_object_t *h,
-                                   omapi_object_t *id,
-                                   omapi_data_string_t *name,
-                                   omapi_typed_data_t *value)
+static isc_result_t
+class_set_value (omapi_object_t *h,
+                omapi_object_t *id,
+                omapi_data_string_t *name,
+                omapi_typed_data_t *value)
 {
        struct class *class;
+       struct class *superclass = 0;
        isc_result_t status;
-       int foo;
+       int issubclass = (h -> type == dhcp_type_subclass);
 
-       if (h -> type != dhcp_type_class)
-               return ISC_R_INVALIDARG;
        class = (struct class *)h;
 
-       /* No values to set yet. */
+       if (!omapi_ds_strcmp (name, "name")) {
+               char *tname;
+
+               if (class -> name)
+                       return ISC_R_EXISTS;
+
+               if ((tname = dmalloc (value -> u.buffer.len+1, MDL)) == NULL) {
+                       return ISC_R_NOMEMORY;
+               }
+               
+               memcpy (tname, value -> u.buffer.value, value -> u.buffer.len);
+
+               if (issubclass) {
+                       status = find_class(&superclass, tname, MDL);
+                       dfree(tname, MDL);
+                       
+                       if (status == ISC_R_NOTFOUND)
+                               return status;
+                       
+                       if (class -> superclass != 0) {
+                               class_dereference(&class -> superclass, MDL);
+                       }
+               
+                       class_reference(&class -> superclass,
+                                       superclass, MDL);
+               } 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;
+
+                       memcpy (class -> name,
+                               value -> u.buffer.value,
+                               value -> u.buffer.len);
+                       class -> name [value -> u.buffer.len] = 0;
+               } else {
+                       return ISC_R_INVALIDARG;
+               }
+               
+               return ISC_R_SUCCESS;
+       }
+
+
+       if (issubclass && !omapi_ds_strcmp(name, "hashstring")) {
+               if (class -> hash_string.data)
+                       return ISC_R_EXISTS;
+               
+               if (value -> type == omapi_datatype_data ||
+                   value -> type == omapi_datatype_string) {
+                       if (!buffer_allocate (&class -> hash_string.buffer,
+                                             value -> u.buffer.len, MDL))
+                               return ISC_R_NOMEMORY;
+                       class->hash_string.data =
+                               &class->hash_string.buffer -> data[0];
+                       memcpy (class -> hash_string.buffer -> data,
+                               value -> u.buffer.value,
+                               value -> u.buffer.len);
+                       class -> hash_string.len = value -> u.buffer.len;
+               } else
+                   return ISC_R_INVALIDARG;
+               return ISC_R_SUCCESS;
+       }
+
+       
+
+       if (!omapi_ds_strcmp (name, "group")) {
+               if (value -> type == omapi_datatype_data ||
+                   value -> type == omapi_datatype_string) {
+                       struct group_object *group;
+                       group = (struct group_object *)0;
+                       group_hash_lookup (&group, group_name_hash,
+                                          (char *)value -> u.buffer.value,
+                                          value -> u.buffer.len, MDL);
+                       if (!group || (group -> flags & GROUP_OBJECT_DELETED))
+                               return ISC_R_NOTFOUND;
+                       if (class -> group)
+                               group_dereference (&class -> group, MDL);
+                       group_reference (&class -> group, group -> group, MDL);
+                       group_object_dereference (&group, MDL);
+               } else
+                       return ISC_R_INVALIDARG;
+               return ISC_R_SUCCESS;
+       }
+
+
+       if (!omapi_ds_strcmp (name, "match")) {
+               if (value -> type == omapi_datatype_data ||
+                   value -> type == omapi_datatype_string) {
+                       /* XXXJAB support 'match hardware' here. */
+                       return ISC_R_INVALIDARG; /* XXX tmp */
+               } else {
+                       return ISC_R_INVALIDARG;
+               }
+               
+               return ISC_R_SUCCESS;
+       }
+
+
+       if (!omapi_ds_strcmp (name, "option")) {
+               if (value -> type == omapi_datatype_data ||
+                   value -> type == omapi_datatype_string) {
+                       /* XXXJAB support 'options' here. */
+                       /* XXXJAB specifically 'bootfile-name' */
+                       return ISC_R_INVALIDARG; /* XXX tmp */
+               } 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) {
@@ -1598,6 +1710,24 @@ isc_result_t dhcp_class_set_value  (omapi_object_t *h,
 }
 
 
+
+
+isc_result_t dhcp_class_set_value  (omapi_object_t *h,
+                                   omapi_object_t *id,
+                                   omapi_data_string_t *name,
+                                   omapi_typed_data_t *value)
+{
+       struct class *class;
+       struct class *superclass = 0;
+       isc_result_t status;
+       int foo;
+
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+
+       return class_set_value(h, id, name, value);
+}
+
 isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
                                   omapi_data_string_t *name,
                                   omapi_value_t **value)
@@ -1609,7 +1739,9 @@ isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
                return ISC_R_INVALIDARG;
        class = (struct class *)h;
 
-       /* No values to get yet. */
+       if (!omapi_ds_strcmp (name, "name"))
+               return omapi_make_string_value (value, name, class -> name,
+                                               MDL);
 
        /* Try to find some inner object that can provide the value. */
        if (h -> inner && h -> inner -> type -> get_value) {
@@ -1618,6 +1750,7 @@ isc_result_t dhcp_class_get_value (omapi_object_t *h, omapi_object_t *id,
                if (status == ISC_R_SUCCESS)
                        return status;
        }
+
        return ISC_R_NOTFOUND;
 }
 
@@ -1630,23 +1763,68 @@ isc_result_t dhcp_class_destroy (omapi_object_t *h, const char *file, int line)
                return ISC_R_INVALIDARG;
        class = (struct class *)h;
 
-       /* Can't destroy classs yet. */
+       /* Can't destroy class yet. */
 
        return ISC_R_SUCCESS;
 }
 
-isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
-                                       const char *name, va_list ap)
+static isc_result_t
+class_signal_handler(omapi_object_t *h,
+                    const char *name, va_list ap)
 {
-       struct class *class;
+       struct class *class = (struct class *)h;
        isc_result_t status;
        int updatep = 0;
+       int issubclass;
 
-       if (h -> type != dhcp_type_class)
-               return ISC_R_INVALIDARG;
-       class = (struct class *)h;
+       issubclass = (h -> type == dhcp_type_subclass);
+
+       if (!strcmp (name, "updated")) {
+               
+               if (!issubclass) {
+                       if (class -> name == 0 || strlen(class -> name) == 0) {
+                               return ISC_R_INVALIDARG;
+                       }
+               } else {
+                       if (class -> superclass == 0) {
+                               return ISC_R_INVALIDARG; /* didn't give name */
+                       }
 
-       /* Can't write classs yet. */
+                       if (class -> hash_string.data == NULL) {
+                               return ISC_R_INVALIDARG;
+                       }
+               }
+
+
+               if (issubclass) {
+                       if (!class -> superclass -> hash) {
+                               class -> superclass -> hash =
+                                       new_hash ((hash_reference)
+                                                 omapi_object_reference,
+                                                 (hash_dereference)
+                                                 omapi_object_dereference, 0);
+                       }
+                       add_hash (class -> superclass -> hash,
+                                 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);
+               } else {
+                       log_debug ("OMAPI added class %s", class -> name);
+               }
+#endif
+               
+               status = enter_class (class, 1, 1);
+               if (status != ISC_R_SUCCESS)
+                       return status;
+               updatep = 1;
+       }
 
        /* Try to find some inner object that can take the value. */
        if (h -> inner && h -> inner -> type -> signal_handler) {
@@ -1655,11 +1833,23 @@ isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
                if (status == ISC_R_SUCCESS)
                        return status;
        }
+
        if (updatep)
                return ISC_R_SUCCESS;
+       
        return ISC_R_NOTFOUND;
 }
 
+
+isc_result_t dhcp_class_signal_handler (omapi_object_t *h,
+                                       const char *name, va_list ap)
+{
+       if (h -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+
+       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)
@@ -1684,32 +1874,124 @@ isc_result_t dhcp_class_stuff_values (omapi_object_t *c,
        return ISC_R_SUCCESS;
 }
 
-isc_result_t dhcp_class_lookup (omapi_object_t **lp,
-                               omapi_object_t *id, omapi_object_t *ref)
+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 *tv = (omapi_value_t *)0;
+       omapi_value_t *nv = (omapi_value_t *)0;
+       omapi_value_t *hv = (omapi_value_t *)0;
        isc_result_t status;
-       struct class *class;
+       struct class *class = 0;
+       struct class *subclass = 0;
 
-       /* Can't look up classs yet. */
+       *lp = NULL;
+       
+       /* see if we have a name */
+       status = omapi_get_value_str (ref, id, "name", &nv);
+       if (status == ISC_R_SUCCESS) {
+               char *name = dmalloc(nv -> value -> u.buffer.len + 1, MDL);
+               memcpy (name,
+                       nv -> value -> u.buffer.value,
+                       nv -> value -> u.buffer.len);
 
-       /* If we get to here without finding a class, no valid key was
-          specified. */
-       if (!*lp)
-               return ISC_R_NOKEYS;
-       return ISC_R_SUCCESS;
+               omapi_value_dereference (&nv, MDL);
+
+               find_class(&class, name, MDL);
+
+               dfree(name, MDL);
+               
+               if (class == NULL) {
+                       return ISC_R_NOTFOUND;
+               }
+
+               if (typewanted == dhcp_type_subclass) {
+                       status = omapi_get_value_str (ref, id,
+                                                     "hashstring", &hv);
+                       if (status != ISC_R_SUCCESS) {
+                               class_dereference(&class, MDL);
+                               return ISC_R_NOKEYS;
+                       }
+
+                       if (hv -> value -> type != omapi_datatype_data &&
+                           hv -> value -> type != omapi_datatype_string) {
+                               class_dereference(&class, MDL);
+                               omapi_value_dereference (&hv, MDL);
+                               return ISC_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_dereference(&class, MDL);
+                       
+                       if (subclass == NULL) {
+                               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 ISC_R_INVALIDARG;
+               }
+               
+               if (class -> flags & CLASS_DECL_DELETED) {
+                       class_dereference (&class, MDL);
+               }
+
+               omapi_object_reference(lp, (omapi_object_t *)class, MDL);
+               
+               return ISC_R_SUCCESS;
+       }
+
+       return ISC_R_NOKEYS;
+}
+
+
+isc_result_t dhcp_class_lookup (omapi_object_t **lp,
+                               omapi_object_t *id, omapi_object_t *ref)
+{
+       return class_lookup(lp, id, ref, dhcp_type_class);
 }
 
 isc_result_t dhcp_class_create (omapi_object_t **lp,
                                omapi_object_t *id)
 {
-       return ISC_R_NOTIMPLEMENTED;
+       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;
 }
 
 isc_result_t dhcp_class_remove (omapi_object_t *lp,
                                omapi_object_t *id)
 {
-       return ISC_R_NOTIMPLEMENTED;
+       struct class *cp;
+       if (lp -> type != dhcp_type_class)
+               return ISC_R_INVALIDARG;
+       cp = (struct class *)lp;
+
+#ifdef DEBUG_OMAPI
+       log_debug ("OMAPI delete class %s", cp -> name);
+#endif
+       
+       delete_class (cp, 1);
+       return ISC_R_SUCCESS;
 }
 
 isc_result_t dhcp_subclass_set_value  (omapi_object_t *h,
@@ -1717,25 +1999,15 @@ isc_result_t dhcp_subclass_set_value  (omapi_object_t *h,
                                       omapi_data_string_t *name,
                                       omapi_typed_data_t *value)
 {
-       struct subclass *subclass;
+       struct class *subclass = 0;
+       struct class *superclass = 0;
        isc_result_t status;
        int foo;
 
        if (h -> type != dhcp_type_subclass)
                return ISC_R_INVALIDARG;
-       subclass = (struct subclass *)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;
+       return class_set_value(h, id, name, value);
 }
 
 
@@ -1743,14 +2015,16 @@ isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
                                      omapi_data_string_t *name,
                                      omapi_value_t **value)
 {
-       struct subclass *subclass;
+       struct class *subclass;
        isc_result_t status;
 
-       if (h -> type != dhcp_type_subclass)
+       if (h -> type != dhcp_type_class)
                return ISC_R_INVALIDARG;
-       subclass = (struct subclass *)h;
-
-       /* No values to get yet. */
+       subclass = (struct class *)h;
+       if (subclass -> name != 0)
+               return ISC_R_INVALIDARG;
+       
+       /* XXXJAB No values to get yet. */
 
        /* Try to find some inner object that can provide the value. */
        if (h -> inner && h -> inner -> type -> get_value) {
@@ -1759,20 +2033,24 @@ isc_result_t dhcp_subclass_get_value (omapi_object_t *h, omapi_object_t *id,
                if (status == ISC_R_SUCCESS)
                        return status;
        }
+
        return ISC_R_NOTFOUND;
 }
 
 isc_result_t dhcp_subclass_destroy (omapi_object_t *h,
                                    const char *file, int line)
 {
-       struct subclass *subclass;
+       struct class *subclass;
        isc_result_t status;
 
-       if (h -> type != dhcp_type_subclass)
+       if (h -> type != dhcp_type_class)
                return ISC_R_INVALIDARG;
-       subclass = (struct subclass *)h;
+       subclass = (struct class *)h;
+       if (subclass -> name != 0)
+               return ISC_R_INVALIDARG;
+       
 
-       /* Can't destroy subclasss yet. */
+       /* XXXJAB Can't destroy subclasss yet. */
 
        return ISC_R_SUCCESS;
 }
@@ -1780,38 +2058,26 @@ isc_result_t dhcp_subclass_destroy (omapi_object_t *h,
 isc_result_t dhcp_subclass_signal_handler (omapi_object_t *h,
                                           const char *name, va_list ap)
 {
-       struct subclass *subclass;
-       isc_result_t status;
-       int updatep = 0;
-
        if (h -> type != dhcp_type_subclass)
                return ISC_R_INVALIDARG;
-       subclass = (struct subclass *)h;
 
-       /* Can't write subclasss yet. */
-
-       /* 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 (status == ISC_R_SUCCESS)
-                       return status;
-       }
-       if (updatep)
-               return ISC_R_SUCCESS;
-       return ISC_R_NOTFOUND;
+       return class_signal_handler(h, name, ap);
 }
 
+
 isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
                                         omapi_object_t *id,
                                         omapi_object_t *h)
 {
-       struct subclass *subclass;
+       struct class *subclass;
        isc_result_t status;
 
-       if (h -> type != dhcp_type_subclass)
+       if (h -> type != dhcp_type_class)
                return ISC_R_INVALIDARG;
-       subclass = (struct subclass *)h;
+       subclass = (struct class *)h;
+       if (subclass -> name != 0)
+               return ISC_R_INVALIDARG;
+       
 
        /* Can't stuff subclass values yet. */
 
@@ -1829,29 +2095,67 @@ isc_result_t dhcp_subclass_stuff_values (omapi_object_t *c,
 isc_result_t dhcp_subclass_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 subclass *subclass;
+       return class_lookup(lp, id, ref, dhcp_type_subclass);
+}
+
 
-       /* Can't look up subclasss yet. */
 
-       /* If we get to here without finding a subclass, no valid key was
-          specified. */
-       if (!*lp)
-               return ISC_R_NOKEYS;
-       return ISC_R_SUCCESS;
-}
 
 isc_result_t dhcp_subclass_create (omapi_object_t **lp,
                                   omapi_object_t *id)
 {
-       return ISC_R_NOTIMPLEMENTED;
+       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);
+
+       cp -> flags = CLASS_DECL_DYNAMIC;
+       
+       status = omapi_object_reference (lp, (omapi_object_t *)cp, MDL);
+       subclass_dereference (&cp, MDL);
+       return status;
 }
 
 isc_result_t dhcp_subclass_remove (omapi_object_t *lp,
                                   omapi_object_t *id)
 {
-       return ISC_R_NOTIMPLEMENTED;
+#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 ISC_R_INVALIDARG;
+       cp = (struct class *)lp;
+
+#ifdef DEBUG_OMAPI
+       log_debug ("OMAPI delete subclass %s", cp -> name);
+#endif
+       
+       delete_class (cp, 1);
+
+#endif
+       
+       return ISC_R_SUCCESS;
 }
 
 /* vim: set tabstop=8: */
index d374d3cb59821b51798eee2d11388a0af5cff004..d4460bed3a8bfb65374065924afed1ab16ec9676 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: salloc.c,v 1.2 2001/04/27 21:30:15 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: salloc.c,v 1.3 2001/06/22 16:47:20 brister Exp $ Copyright (c) 1996-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -60,6 +60,7 @@ struct lease *new_leases (n, file, line)
 
 OMAPI_OBJECT_ALLOC (lease, struct lease, dhcp_type_lease)
 OMAPI_OBJECT_ALLOC (class, struct class, dhcp_type_class)
+OMAPI_OBJECT_ALLOC (subclass, struct class, dhcp_type_subclass)
 OMAPI_OBJECT_ALLOC (pool, struct pool, dhcp_type_pool)
 
 #if !defined (NO_HOST_FREES)   /* Scary debugging mode - don't enable! */