]>
Commit | Line | Data |
---|---|---|
07378a2a TL |
1 | /* class.c |
2 | ||
3 | Handling for client classes. */ | |
4 | ||
5 | /* | |
49733f31 TL |
6 | * Copyright (c) 1998-2000 Internet Software Consortium. |
7 | * All rights reserved. | |
07378a2a | 8 | * |
49733f31 TL |
9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
07378a2a | 12 | * |
49733f31 TL |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | |
18 | * 3. Neither the name of The Internet Software Consortium nor the names | |
19 | * of its contributors may be used to endorse or promote products derived | |
20 | * from this software without specific prior written permission. | |
07378a2a | 21 | * |
49733f31 TL |
22 | * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND |
23 | * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
24 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
26 | * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR | |
27 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
28 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
29 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
30 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
31 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
33 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
34 | * SUCH DAMAGE. | |
35 | * | |
36 | * This software has been written for the Internet Software Consortium | |
37 | * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. | |
38 | * To learn more about the Internet Software Consortium, see | |
39 | * ``http://www.isc.org/''. To learn more about Vixie Enterprises, | |
40 | * see ``http://www.vix.com''. To learn more about Nominum, Inc., see | |
41 | * ``http://www.nominum.com''. | |
07378a2a TL |
42 | */ |
43 | ||
44 | #ifndef lint | |
45 | static char copyright[] = | |
fea20b09 | 46 | "$Id: class.c,v 1.28 2001/04/06 05:45:45 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n"; |
49733f31 | 47 | |
07378a2a TL |
48 | #endif /* not lint */ |
49 | ||
50 | #include "dhcpd.h" | |
51 | ||
07378a2a TL |
52 | struct collection default_collection = { |
53 | (struct collection *)0, | |
54 | "default", | |
55 | (struct class *)0, | |
56 | }; | |
57 | ||
05129661 | 58 | struct collection *collections = &default_collection; |
adb7ed1a | 59 | struct executable_statement *default_classification_rules; |
07378a2a | 60 | |
ee7b5624 TL |
61 | int have_billing_classes; |
62 | ||
07378a2a TL |
63 | /* Build the default classification rule tree. */ |
64 | ||
65 | void classification_setup () | |
66 | { | |
adb7ed1a | 67 | struct executable_statement *rules; |
07378a2a | 68 | |
07378a2a | 69 | /* eval ... */ |
dce08243 | 70 | rules = (struct executable_statement *)0; |
12c9957e | 71 | if (!executable_statement_allocate (&rules, MDL)) |
8ae2d595 | 72 | log_fatal ("Can't allocate check of default collection"); |
adb7ed1a | 73 | rules -> op = eval_statement; |
07378a2a | 74 | |
dce08243 | 75 | /* check-collection "default" */ |
12c9957e | 76 | if (!expression_allocate (&rules -> data.eval, MDL)) |
dce08243 TL |
77 | log_fatal ("Can't allocate default check expression"); |
78 | rules -> data.eval -> op = expr_check; | |
79 | rules -> data.eval -> data.check = &default_collection; | |
80 | ||
05129661 | 81 | default_classification_rules = rules; |
07378a2a TL |
82 | } |
83 | ||
84 | void classify_client (packet) | |
85 | struct packet *packet; | |
86 | { | |
9e383163 TL |
87 | execute_statements ((struct binding_value **)0, packet, |
88 | (struct lease *)0, (struct client_state *)0, | |
89 | packet -> options, (struct option_state *)0, | |
90 | &global_scope, default_classification_rules); | |
07378a2a TL |
91 | } |
92 | ||
da38df14 | 93 | int check_collection (packet, lease, collection) |
07378a2a | 94 | struct packet *packet; |
da38df14 | 95 | struct lease *lease; |
07378a2a TL |
96 | struct collection *collection; |
97 | { | |
98 | struct class *class, *nc; | |
99 | struct data_string data; | |
100 | int matched = 0; | |
4af075a2 | 101 | int status; |
63f8b323 | 102 | int ignorep; |
07378a2a TL |
103 | |
104 | for (class = collection -> classes; class; class = class -> nic) { | |
74a2049e | 105 | #if defined (DEBUG_CLASS_MATCHING) |
8ae2d595 | 106 | log_info ("checking against class %s...", class -> name); |
74a2049e | 107 | #endif |
ee7b5624 | 108 | memset (&data, 0, sizeof data); |
56120203 TL |
109 | |
110 | /* If there is a "match if" expression, check it. If | |
111 | we get a match, and there's no subclass expression, | |
112 | it's a match. If we get a match and there is a subclass | |
113 | expression, then we check the submatch. If it's not a | |
114 | match, that's final - we don't check the submatch. */ | |
115 | ||
116 | if (class -> expr) { | |
117 | status = (evaluate_boolean_expression_result | |
118 | (&ignorep, packet, lease, | |
9e383163 | 119 | (struct client_state *)0, |
56120203 | 120 | packet -> options, (struct option_state *)0, |
eaa84150 TL |
121 | lease ? &lease -> scope : &global_scope, |
122 | class -> expr)); | |
56120203 TL |
123 | if (status) { |
124 | if (!class -> submatch) { | |
125 | matched = 1; | |
126 | #if defined (DEBUG_CLASS_MATCHING) | |
127 | log_info ("matches class."); | |
128 | #endif | |
129 | classify (packet, class); | |
130 | continue; | |
131 | } | |
132 | } else | |
133 | continue; | |
134 | } | |
135 | ||
136 | /* Check to see if the client matches an existing subclass. | |
137 | If it doesn't, and this is a spawning class, spawn a new | |
138 | subclass and put the client in it. */ | |
8b500185 | 139 | if (class -> submatch) { |
dce08243 TL |
140 | status = (evaluate_data_expression |
141 | (&data, packet, lease, | |
9e383163 | 142 | (struct client_state *)0, |
dce08243 | 143 | packet -> options, (struct option_state *)0, |
5b5fcc81 TL |
144 | lease ? &lease -> scope : &global_scope, |
145 | class -> submatch)); | |
b767664e | 146 | if (status && data.len) { |
20916cae TL |
147 | nc = (struct class *)0; |
148 | if (class_hash_lookup (&nc, class -> hash, | |
149 | (const char *)data.data, | |
150 | data.len, MDL)) { | |
74a2049e | 151 | #if defined (DEBUG_CLASS_MATCHING) |
8ae2d595 | 152 | log_info ("matches subclass %s.", |
ee7b5624 TL |
153 | print_hex_1 (data.len, |
154 | data.data, 60)); | |
155 | #endif | |
12c9957e | 156 | data_string_forget (&data, MDL); |
ee7b5624 TL |
157 | classify (packet, nc); |
158 | matched = 1; | |
a19e8a45 | 159 | class_dereference (&nc, MDL); |
ee7b5624 TL |
160 | continue; |
161 | } | |
12c9957e TL |
162 | if (!class -> spawning) { |
163 | data_string_forget (&data, MDL); | |
8b500185 | 164 | continue; |
12c9957e | 165 | } |
fea20b09 | 166 | /* XXX Write out the spawned class? */ |
ee7b5624 | 167 | #if defined (DEBUG_CLASS_MATCHING) |
8ae2d595 | 168 | log_info ("spawning subclass %s.", |
64e1dc1d | 169 | print_hex_1 (data.len, data.data, 60)); |
74a2049e | 170 | #endif |
a19e8a45 TL |
171 | status = class_allocate (&nc, MDL); |
172 | group_reference (&nc -> group, | |
173 | class -> group, MDL); | |
174 | class_reference (&nc -> superclass, | |
175 | class, MDL); | |
ee7b5624 TL |
176 | nc -> lease_limit = class -> lease_limit; |
177 | nc -> dirty = 1; | |
178 | if (nc -> lease_limit) { | |
179 | nc -> billed_leases = | |
180 | (dmalloc | |
181 | (nc -> lease_limit * | |
182 | sizeof (struct lease *), | |
12c9957e | 183 | MDL)); |
ee7b5624 | 184 | if (!nc -> billed_leases) { |
7e6f3635 TL |
185 | log_error ("no memory for%s", |
186 | " billing"); | |
ee7b5624 TL |
187 | data_string_forget |
188 | (&nc -> hash_string, | |
12c9957e | 189 | MDL); |
a19e8a45 | 190 | class_dereference (&nc, MDL); |
12c9957e TL |
191 | data_string_forget (&data, |
192 | MDL); | |
ee7b5624 TL |
193 | continue; |
194 | } | |
195 | memset (nc -> billed_leases, 0, | |
196 | (nc -> lease_limit * | |
197 | sizeof nc -> billed_leases)); | |
198 | } | |
199 | data_string_copy (&nc -> hash_string, &data, | |
12c9957e TL |
200 | MDL); |
201 | data_string_forget (&data, MDL); | |
ee7b5624 | 202 | if (!class -> hash) |
7d9784f6 | 203 | class -> hash = new_hash (0, 0, 0); |
20916cae TL |
204 | class_hash_add (class -> hash, |
205 | (const char *) | |
206 | nc -> hash_string.data, | |
207 | nc -> hash_string.len, | |
208 | nc, MDL); | |
ee7b5624 | 209 | classify (packet, nc); |
07378a2a TL |
210 | } |
211 | } | |
07378a2a TL |
212 | } |
213 | return matched; | |
214 | } | |
215 | ||
216 | void classify (packet, class) | |
217 | struct packet *packet; | |
218 | struct class *class; | |
219 | { | |
220 | if (packet -> class_count < PACKET_MAX_CLASSES) | |
20916cae TL |
221 | class_reference (&packet -> classes [packet -> class_count++], |
222 | class, MDL); | |
07378a2a | 223 | else |
8ae2d595 | 224 | log_error ("too many groups for %s", |
07378a2a TL |
225 | print_hw_addr (packet -> raw -> htype, |
226 | packet -> raw -> hlen, | |
227 | packet -> raw -> chaddr)); | |
228 | } | |
229 | ||
20916cae TL |
230 | isc_result_t find_class (struct class **class, const char *name, |
231 | const char *file, int line) | |
adb7ed1a TL |
232 | { |
233 | struct collection *lp; | |
234 | struct class *cp; | |
235 | ||
236 | for (lp = collections; lp; lp = lp -> next) { | |
237 | for (cp = lp -> classes; cp; cp = cp -> nic) | |
20916cae TL |
238 | if (cp -> name && !strcmp (name, cp -> name)) { |
239 | return class_reference (class, cp, file, line); | |
240 | } | |
adb7ed1a | 241 | } |
20916cae | 242 | return ISC_R_NOTFOUND; |
adb7ed1a | 243 | } |
ee7b5624 TL |
244 | |
245 | int unbill_class (lease, class) | |
246 | struct lease *lease; | |
247 | struct class *class; | |
248 | { | |
249 | int i; | |
250 | ||
251 | for (i = 0; i < class -> lease_limit; i++) | |
252 | if (class -> billed_leases [i] == lease) | |
253 | break; | |
254 | if (i == class -> lease_limit) { | |
8ae2d595 | 255 | log_error ("lease %s unbilled with no billing arrangement.", |
ee7b5624 TL |
256 | piaddr (lease -> ip_addr)); |
257 | return 0; | |
258 | } | |
20916cae TL |
259 | class_dereference (&lease -> billing_class, MDL); |
260 | lease_dereference (&class -> billed_leases [i], MDL); | |
ee7b5624 TL |
261 | class -> leases_consumed--; |
262 | return 1; | |
263 | } | |
264 | ||
265 | int bill_class (lease, class) | |
266 | struct lease *lease; | |
267 | struct class *class; | |
268 | { | |
269 | int i; | |
270 | ||
271 | if (class -> leases_consumed == class -> lease_limit) | |
272 | return 0; | |
273 | ||
274 | for (i = 0; i < class -> lease_limit; i++) | |
275 | if (!class -> billed_leases [i]) | |
276 | break; | |
277 | ||
278 | if (i == class -> lease_limit) { | |
8ae2d595 | 279 | log_error ("class billing consumption disagrees with leases."); |
ee7b5624 TL |
280 | return 0; |
281 | } | |
282 | ||
20916cae TL |
283 | lease_reference (&class -> billed_leases [i], lease, MDL); |
284 | class_reference (&lease -> billing_class, class, MDL); | |
ee7b5624 TL |
285 | class -> leases_consumed++; |
286 | return 1; | |
287 | } |