3 Handling for client classes. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1998-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
36 static char copyright
[] =
37 "$Id: class.c,v 1.4 2005/08/11 17:13:30 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
43 struct collection default_collection
= {
44 (struct collection
*)0,
49 struct collection
*collections
= &default_collection
;
50 struct executable_statement
*default_classification_rules
;
52 int have_billing_classes
;
54 /* Build the default classification rule tree. */
56 void classification_setup ()
59 default_classification_rules
= (struct executable_statement
*)0;
60 if (!executable_statement_allocate (&default_classification_rules
,
62 log_fatal ("Can't allocate check of default collection");
63 default_classification_rules
-> op
= eval_statement
;
65 /* check-collection "default" */
66 if (!expression_allocate (&default_classification_rules
-> data
.eval
,
68 log_fatal ("Can't allocate default check expression");
69 default_classification_rules
-> data
.eval
-> op
= expr_check
;
70 default_classification_rules
-> data
.eval
-> data
.check
=
74 void classify_client (packet
)
75 struct packet
*packet
;
77 execute_statements ((struct binding_value
**)0, packet
,
78 (struct lease
*)0, (struct client_state
*)0,
79 packet
-> options
, (struct option_state
*)0,
80 &global_scope
, default_classification_rules
);
83 int check_collection (packet
, lease
, collection
)
84 struct packet
*packet
;
86 struct collection
*collection
;
88 struct class *class, *nc
;
89 struct data_string data
;
94 for (class = collection
-> classes
; class; class = class -> nic
) {
95 #if defined (DEBUG_CLASS_MATCHING)
96 log_info ("checking against class %s...", class -> name
);
98 memset (&data
, 0, sizeof data
);
100 /* If there is a "match if" expression, check it. If
101 we get a match, and there's no subclass expression,
102 it's a match. If we get a match and there is a subclass
103 expression, then we check the submatch. If it's not a
104 match, that's final - we don't check the submatch. */
107 status
= (evaluate_boolean_expression_result
108 (&ignorep
, packet
, lease
,
109 (struct client_state
*)0,
110 packet
-> options
, (struct option_state
*)0,
111 lease
? &lease
-> scope
: &global_scope
,
114 if (!class -> submatch
) {
116 #if defined (DEBUG_CLASS_MATCHING)
117 log_info ("matches class.");
119 classify (packet
, class);
126 /* Check to see if the client matches an existing subclass.
127 If it doesn't, and this is a spawning class, spawn a new
128 subclass and put the client in it. */
129 if (class -> submatch
) {
130 status
= (evaluate_data_expression
131 (&data
, packet
, lease
,
132 (struct client_state
*)0,
133 packet
-> options
, (struct option_state
*)0,
134 lease
? &lease
-> scope
: &global_scope
,
135 class -> submatch
, MDL
));
136 if (status
&& data
.len
) {
137 nc
= (struct class *)0;
138 if (class_hash_lookup (&nc
, class -> hash
,
139 (const char *)data
.data
,
141 #if defined (DEBUG_CLASS_MATCHING)
142 log_info ("matches subclass %s.",
143 print_hex_1 (data
.len
,
146 data_string_forget (&data
, MDL
);
147 classify (packet
, nc
);
149 class_dereference (&nc
, MDL
);
152 if (!class -> spawning
) {
153 data_string_forget (&data
, MDL
);
156 /* XXX Write out the spawned class? */
157 #if defined (DEBUG_CLASS_MATCHING)
158 log_info ("spawning subclass %s.",
159 print_hex_1 (data
.len
, data
.data
, 60));
161 status
= class_allocate (&nc
, MDL
);
162 group_reference (&nc
-> group
,
163 class -> group
, MDL
);
164 class_reference (&nc
-> superclass
,
166 nc
-> lease_limit
= class -> lease_limit
;
168 if (nc
-> lease_limit
) {
169 nc
-> billed_leases
=
172 sizeof (struct lease
*),
174 if (!nc
-> billed_leases
) {
175 log_error ("no memory for%s",
180 class_dereference (&nc
, MDL
);
181 data_string_forget (&data
,
185 memset (nc
-> billed_leases
, 0,
187 sizeof nc
-> billed_leases
));
189 data_string_copy (&nc
-> hash_string
, &data
,
191 data_string_forget (&data
, MDL
);
193 class_new_hash (&class -> hash
, 0, MDL
);
194 class_hash_add (class -> hash
,
196 nc
-> hash_string
.data
,
197 nc
-> hash_string
.len
,
199 classify (packet
, nc
);
200 class_dereference (&nc
, MDL
);
207 void classify (packet
, class)
208 struct packet
*packet
;
211 if (packet
-> class_count
< PACKET_MAX_CLASSES
)
212 class_reference (&packet
-> classes
[packet
-> class_count
++],
215 log_error ("too many classes match %s",
216 print_hw_addr (packet
-> raw
-> htype
,
217 packet
-> raw
-> hlen
,
218 packet
-> raw
-> chaddr
));
221 isc_result_t
find_class (struct class **class, const char *name
,
222 const char *file
, int line
)
224 struct collection
*lp
;
227 for (lp
= collections
; lp
; lp
= lp
-> next
) {
228 for (cp
= lp
-> classes
; cp
; cp
= cp
-> nic
)
229 if (cp
-> name
&& !strcmp (name
, cp
-> name
)) {
230 return class_reference (class, cp
, file
, line
);
233 return ISC_R_NOTFOUND
;
236 int unbill_class (lease
, class)
242 for (i
= 0; i
< class -> lease_limit
; i
++)
243 if (class -> billed_leases
[i
] == lease
)
245 if (i
== class -> lease_limit
) {
246 log_error ("lease %s unbilled with no billing arrangement.",
247 piaddr (lease
-> ip_addr
));
250 class_dereference (&lease
-> billing_class
, MDL
);
251 lease_dereference (&class -> billed_leases
[i
], MDL
);
252 class -> leases_consumed
--;
256 int bill_class (lease
, class)
262 if (lease
-> billing_class
) {
263 log_error ("lease billed with existing billing arrangement.");
264 unbill_class (lease
, lease
-> billing_class
);
267 if (class -> leases_consumed
== class -> lease_limit
)
270 for (i
= 0; i
< class -> lease_limit
; i
++)
271 if (!class -> billed_leases
[i
])
274 if (i
== class -> lease_limit
) {
275 log_error ("class billing consumption disagrees with leases.");
279 lease_reference (&class -> billed_leases
[i
], lease
, MDL
);
280 class_reference (&lease
-> billing_class
, class, MDL
);
281 class -> leases_consumed
++;