]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Add class billing support.
authorTed Lemon <source@isc.org>
Wed, 11 Nov 1998 07:58:35 +0000 (07:58 +0000)
committerTed Lemon <source@isc.org>
Wed, 11 Nov 1998 07:58:35 +0000 (07:58 +0000)
server/class.c

index 3a90376cb6a8a742140ee9ccf8ae807f30645d97..7f403f6c1bca5e8ce3942456250542616081275e 100644 (file)
@@ -42,7 +42,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: class.c,v 1.6 1998/11/09 02:46:19 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: class.c,v 1.7 1998/11/11 07:58:35 mellon Exp $ Copyright (c) 1998 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -137,28 +137,6 @@ static char copyright[] =
  *
  */
 
-struct class unknown_class = {
-       (struct class *)0,
-       "unknown",
-       0,
-       (struct lease *)0,
-       (struct hash_table *)0,
-       (struct expression *)0,
-       (struct expression *)0,
-       (struct group *)0,
-};
-
-struct class known_class = {
-       (struct class *)0,
-       "unknown",
-       0,
-       (struct lease *)0,
-       (struct hash_table *)0,
-       (struct expression *)0,
-       (struct expression *)0,
-       (struct group *)0,
-};
-
 struct collection default_collection = {
        (struct collection *)0,
        "default",
@@ -168,6 +146,8 @@ struct collection default_collection = {
 struct collection *collections = &default_collection;
 struct executable_statement *default_classification_rules;
 
+int have_billing_classes;
+
 /* Build the default classification rule tree. */
 
 void classification_setup ()
@@ -218,25 +198,73 @@ int check_collection (packet, collection)
 #if defined (DEBUG_CLASS_MATCHING)
                note ("checking against class %s...", class -> name);
 #endif
-               if (class -> hash) {
-                       memset (&data, 0, sizeof data);
+               memset (&data, 0, sizeof data);
+               /* If a class is for billing, don't put the client in the
+                  class if we've already billed it to a different class. */
+               if (class -> spawn) {
                        status = evaluate_data_expression (&data, packet,
                                                           &packet -> options,
                                                           class -> spawn);
-                       if (status &&
-                           (nc = (struct class *)hash_lookup (class -> hash,
-                                                              data.data,
-                                                              data.len))) {
+                       if (status) {
+                               if ((nc = ((struct class *)
+                                          hash_lookup (class -> hash,
+                                                       data.data,
+                                                       data.len)))) {
 #if defined (DEBUG_CLASS_MATCHING)
-                               note ("matches subclass %s.",
+                                       note ("matches subclass %s.",
+                                             print_hex_1 (data.len,
+                                                          data.data, 60));
+#endif
+                                       data_string_forget
+                                               (&data, "check_collection");
+                                       classify (packet, nc);
+                                       matched = 1;
+                                       continue;
+                               }
+#if defined (DEBUG_CLASS_MATCHING)
+                               note ("spawning subclass %s.",
                                      print_hex_1 (data.len, data.data, 60));
 #endif
-                               classify (packet, class);
-                               matched = 1;
-                               continue;
+                               nc = (struct class *)
+                                       dmalloc (sizeof (struct class),
+                                                "class spawn");
+                               memset (nc, 0, sizeof *nc);
+                               nc -> group = class -> group;
+                               nc -> superclass = class;
+                               nc -> lease_limit = class -> lease_limit;
+                               nc -> dirty = 1;
+                               if (nc -> lease_limit) {
+                                       nc -> billed_leases =
+                                               (dmalloc
+                                                (nc -> lease_limit *
+                                                 sizeof (struct lease *),
+                                                 "check_collection"));
+                                       if (!nc -> billed_leases) {
+                                               warn ("no memory for billing");
+                                               data_string_forget
+                                                       (&nc -> hash_string,
+                                                        "check_collection");
+                                               dfree (nc, "check_collection");
+                                               continue;
+                                       }
+                                       memset (nc -> billed_leases, 0,
+                                               (nc -> lease_limit *
+                                                sizeof nc -> billed_leases));
+                               }
+                               data_string_copy (&nc -> hash_string, &data,
+                                                 "check_collection");
+                               data_string_forget (&data, "check_collection");
+                               if (!class -> hash)
+                                       class -> hash = new_hash ();
+                               add_hash (class -> hash,
+                                         nc -> hash_string.data,
+                                         nc -> hash_string.len,
+                                         (unsigned char *)nc);
+                               classify (packet, nc);
                        }
+                       data_string_forget (&data, "check_collection");
                }
-               memset (&data, 0, sizeof data);
+
                status = (evaluate_boolean_expression_result
                          (packet, &packet -> options, class -> expr));
                if (status) {
@@ -244,28 +272,8 @@ int check_collection (packet, collection)
 #if defined (DEBUG_CLASS_MATCHING)
                        note ("matches class.");
 #endif
-               }
-               if (status &&
-                   class -> spawn &&
-                   evaluate_data_expression (&data, packet,
-                                             &packet -> options,
-                                             class -> spawn)) {
-#if defined (DEBUG_CLASS_MATCHING)
-                               note ("spawning subclass %s.",
-                                     print_hex_1 (data.len, data.data, 60));
-#endif
-                       nc = (struct class *)
-                               dmalloc (sizeof (struct class), "class spawn");
-                       memset (nc, 0, sizeof *nc);
-                       nc -> group = class -> group;
-                       if (!class -> hash)
-                               class -> hash = new_hash ();
-                       add_hash (class -> hash,
-                                 data.data, data.len,
-                                 (unsigned char *)nc);
-                       classify (packet, nc);
-               } else if (status)
                        classify (packet, class);
+               }
        }
        return matched;
 }
@@ -296,3 +304,47 @@ struct class *find_class (name)
        }
        return (struct class *)0;
 }
+
+int unbill_class (lease, class)
+       struct lease *lease;
+       struct class *class;
+{
+       int i;
+
+       for (i = 0; i < class -> lease_limit; i++)
+               if (class -> billed_leases [i] == lease)
+                       break;
+       if (i == class -> lease_limit) {
+               warn ("lease %s unbilled with no billing arrangement.",
+                     piaddr (lease -> ip_addr));
+               return 0;
+       }
+       lease -> billing_class = (struct class *)0;
+       class -> billed_leases [i] = (struct lease *)0;
+       class -> leases_consumed--;
+       return 1;
+}
+
+int bill_class (lease, class)
+       struct lease *lease;
+       struct class *class;
+{
+       int i;
+
+       if (class -> leases_consumed == class -> lease_limit)
+               return 0;
+
+       for (i = 0; i < class -> lease_limit; i++)
+               if (!class -> billed_leases [i])
+                       break;
+
+       if (i == class -> lease_limit) {
+               warn ("class billing consumption disagrees with leases.");
+               return 0;
+       }
+
+       class -> billed_leases [i] = lease;
+       lease -> billing_class = class;
+       class -> leases_consumed++;
+       return 1;
+}