#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"
*
*/
-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",
struct collection *collections = &default_collection;
struct executable_statement *default_classification_rules;
+int have_billing_classes;
+
/* Build the default classification rule tree. */
void classification_setup ()
#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) {
#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;
}
}
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;
+}