]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/class.c
Finished merge of rt39318 (install embedded bind9 includes and libs)
[thirdparty/dhcp.git] / server / class.c
CommitLineData
07378a2a
TL
1/* class.c
2
3 Handling for client classes. */
4
5/*
6a39bcf0 6 * Copyright (c) 2009,2012-2015 by Internet Systems Consortium, Inc. ("ISC")
0f750c4f 7 * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 8 * Copyright (c) 1998-2003 by Internet Software Consortium
07378a2a 9 *
98311e4b
DH
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
07378a2a 13 *
98311e4b
DH
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
07378a2a 21 *
98311e4b
DH
22 * Internet Systems Consortium, Inc.
23 * 950 Charter Street
24 * Redwood City, CA 94063
25 * <info@isc.org>
2c85ac9b 26 * https://www.isc.org/
49733f31 27 *
07378a2a
TL
28 */
29
07378a2a
TL
30#include "dhcpd.h"
31
07378a2a
TL
32struct collection default_collection = {
33 (struct collection *)0,
34 "default",
35 (struct class *)0,
36};
37
05129661 38struct collection *collections = &default_collection;
adb7ed1a 39struct executable_statement *default_classification_rules;
07378a2a 40
ee7b5624
TL
41int have_billing_classes;
42
07378a2a
TL
43/* Build the default classification rule tree. */
44
45void classification_setup ()
46{
07378a2a 47 /* eval ... */
d758ad8c
TL
48 default_classification_rules = (struct executable_statement *)0;
49 if (!executable_statement_allocate (&default_classification_rules,
50 MDL))
8ae2d595 51 log_fatal ("Can't allocate check of default collection");
d758ad8c 52 default_classification_rules -> op = eval_statement;
07378a2a 53
dce08243 54 /* check-collection "default" */
d758ad8c
TL
55 if (!expression_allocate (&default_classification_rules -> data.eval,
56 MDL))
dce08243 57 log_fatal ("Can't allocate default check expression");
d758ad8c
TL
58 default_classification_rules -> data.eval -> op = expr_check;
59 default_classification_rules -> data.eval -> data.check =
60 &default_collection;
07378a2a
TL
61}
62
63void classify_client (packet)
64 struct packet *packet;
65{
a7341359
SR
66 execute_statements (NULL, packet, NULL, NULL, packet->options, NULL,
67 &global_scope, default_classification_rules, NULL);
07378a2a
TL
68}
69
da38df14 70int check_collection (packet, lease, collection)
07378a2a 71 struct packet *packet;
da38df14 72 struct lease *lease;
07378a2a
TL
73 struct collection *collection;
74{
75 struct class *class, *nc;
76 struct data_string data;
77 int matched = 0;
4af075a2 78 int status;
63f8b323 79 int ignorep;
33692791 80 int classfound;
07378a2a
TL
81
82 for (class = collection -> classes; class; class = class -> nic) {
74a2049e 83#if defined (DEBUG_CLASS_MATCHING)
8ae2d595 84 log_info ("checking against class %s...", class -> name);
74a2049e 85#endif
ee7b5624 86 memset (&data, 0, sizeof data);
56120203
TL
87
88 /* If there is a "match if" expression, check it. If
89 we get a match, and there's no subclass expression,
90 it's a match. If we get a match and there is a subclass
91 expression, then we check the submatch. If it's not a
92 match, that's final - we don't check the submatch. */
93
94 if (class -> expr) {
95 status = (evaluate_boolean_expression_result
96 (&ignorep, packet, lease,
9e383163 97 (struct client_state *)0,
56120203 98 packet -> options, (struct option_state *)0,
eaa84150
TL
99 lease ? &lease -> scope : &global_scope,
100 class -> expr));
56120203
TL
101 if (status) {
102 if (!class -> submatch) {
103 matched = 1;
104#if defined (DEBUG_CLASS_MATCHING)
105 log_info ("matches class.");
106#endif
107 classify (packet, class);
108 continue;
109 }
110 } else
111 continue;
112 }
113
114 /* Check to see if the client matches an existing subclass.
115 If it doesn't, and this is a spawning class, spawn a new
116 subclass and put the client in it. */
8b500185 117 if (class -> submatch) {
dce08243
TL
118 status = (evaluate_data_expression
119 (&data, packet, lease,
9e383163 120 (struct client_state *)0,
dce08243 121 packet -> options, (struct option_state *)0,
5b5fcc81 122 lease ? &lease -> scope : &global_scope,
d758ad8c 123 class -> submatch, MDL));
b767664e 124 if (status && data.len) {
20916cae 125 nc = (struct class *)0;
33692791
DH
126 classfound = class_hash_lookup (&nc, class -> hash,
127 (const char *)data.data, data.len, MDL);
128
129#ifdef LDAP_CONFIGURATION
130 if (!classfound && find_subclass_in_ldap (class, &nc, &data))
131 classfound = 1;
132#endif
133
134 if (classfound) {
74a2049e 135#if defined (DEBUG_CLASS_MATCHING)
8ae2d595 136 log_info ("matches subclass %s.",
ee7b5624
TL
137 print_hex_1 (data.len,
138 data.data, 60));
139#endif
12c9957e 140 data_string_forget (&data, MDL);
ee7b5624
TL
141 classify (packet, nc);
142 matched = 1;
a19e8a45 143 class_dereference (&nc, MDL);
ee7b5624
TL
144 continue;
145 }
12c9957e
TL
146 if (!class -> spawning) {
147 data_string_forget (&data, MDL);
8b500185 148 continue;
12c9957e 149 }
fea20b09 150 /* XXX Write out the spawned class? */
ee7b5624 151#if defined (DEBUG_CLASS_MATCHING)
8ae2d595 152 log_info ("spawning subclass %s.",
64e1dc1d 153 print_hex_1 (data.len, data.data, 60));
74a2049e 154#endif
a19e8a45
TL
155 status = class_allocate (&nc, MDL);
156 group_reference (&nc -> group,
157 class -> group, MDL);
158 class_reference (&nc -> superclass,
159 class, MDL);
ee7b5624
TL
160 nc -> lease_limit = class -> lease_limit;
161 nc -> dirty = 1;
162 if (nc -> lease_limit) {
163 nc -> billed_leases =
164 (dmalloc
165 (nc -> lease_limit *
166 sizeof (struct lease *),
12c9957e 167 MDL));
ee7b5624 168 if (!nc -> billed_leases) {
7e6f3635
TL
169 log_error ("no memory for%s",
170 " billing");
ee7b5624
TL
171 data_string_forget
172 (&nc -> hash_string,
12c9957e 173 MDL);
a19e8a45 174 class_dereference (&nc, MDL);
12c9957e
TL
175 data_string_forget (&data,
176 MDL);
ee7b5624
TL
177 continue;
178 }
179 memset (nc -> billed_leases, 0,
180 (nc -> lease_limit *
0f750c4f 181 sizeof (struct lease *)));
ee7b5624
TL
182 }
183 data_string_copy (&nc -> hash_string, &data,
12c9957e
TL
184 MDL);
185 data_string_forget (&data, MDL);
ee7b5624 186 if (!class -> hash)
f7fdb216
DH
187 class_new_hash(&class->hash,
188 SCLASS_HASH_SIZE, MDL);
20916cae
TL
189 class_hash_add (class -> hash,
190 (const char *)
191 nc -> hash_string.data,
192 nc -> hash_string.len,
193 nc, MDL);
ee7b5624 194 classify (packet, nc);
d758ad8c 195 class_dereference (&nc, MDL);
07378a2a
TL
196 }
197 }
07378a2a
TL
198 }
199 return matched;
200}
201
202void classify (packet, class)
203 struct packet *packet;
204 struct class *class;
205{
206 if (packet -> class_count < PACKET_MAX_CLASSES)
20916cae
TL
207 class_reference (&packet -> classes [packet -> class_count++],
208 class, MDL);
07378a2a 209 else
d758ad8c 210 log_error ("too many classes match %s",
07378a2a
TL
211 print_hw_addr (packet -> raw -> htype,
212 packet -> raw -> hlen,
213 packet -> raw -> chaddr));
214}
215
899d754f
JB
216
217isc_result_t unlink_class(struct class **class) {
218 struct collection *lp;
219 struct class *cp, *pp;
220
221 for (lp = collections; lp; lp = lp -> next) {
222 for (pp = 0, cp = lp -> classes; cp; pp = cp, cp = cp -> nic)
223 if (cp == *class) {
224 if (pp == 0) {
225 lp->classes = cp->nic;
226 } else {
227 pp->nic = cp->nic;
228 }
229 cp->nic = 0;
230 class_dereference(class, MDL);
231
232 return ISC_R_SUCCESS;
233 }
234 }
235 return ISC_R_NOTFOUND;
236}
237
6a39bcf0 238
20916cae
TL
239isc_result_t find_class (struct class **class, const char *name,
240 const char *file, int line)
adb7ed1a
TL
241{
242 struct collection *lp;
243 struct class *cp;
244
245 for (lp = collections; lp; lp = lp -> next) {
246 for (cp = lp -> classes; cp; cp = cp -> nic)
20916cae
TL
247 if (cp -> name && !strcmp (name, cp -> name)) {
248 return class_reference (class, cp, file, line);
249 }
adb7ed1a 250 }
20916cae 251 return ISC_R_NOTFOUND;
adb7ed1a 252}
ee7b5624 253
6a39bcf0
TM
254/* Removes the billing class from a lease
255 *
256 * Note that because classes can be created and removed dynamically, it is
257 * possible that the class to which a lease was billed has since been deleted.
258 * To cover the case where the lease is the last reference to a deleted class
259 * we remove the lease reference from the class first, then the class from the
260 * lease. To protect ourselves from the reverse situation, where the class is
261 * the last reference to the lease (unlikely), we create a guard reference to
262 * the lease, then remove it at the end.
263 */
264void unbill_class (lease)
ee7b5624 265 struct lease *lease;
ee7b5624
TL
266{
267 int i;
6a39bcf0
TM
268 struct class* class = lease->billing_class;
269 struct lease* refholder = NULL;
ee7b5624 270
6a39bcf0
TM
271 /* if there's no billing to remove, nothing to do */
272 if (class == NULL) {
273 return;
274 }
275
276 /* Find the lease in the list of the class's billed leases */
277 for (i = 0; i < class->lease_limit; i++) {
278 if (class->billed_leases[i] == lease)
ee7b5624 279 break;
6a39bcf0
TM
280 }
281
282 /* Create guard reference, so class cannot be last reference to lease */
283 lease_reference(&refholder, lease, MDL);
284
285 /* If the class doesn't have the lease, then something is broken
286 * programmatically. We'll log it but skip the lease dereference. */
287 if (i == class->lease_limit) {
8ae2d595 288 log_error ("lease %s unbilled with no billing arrangement.",
6a39bcf0
TM
289 piaddr(lease->ip_addr));
290 } else {
291 /* Remove the lease from the class */
292 lease_dereference(&class->billed_leases[i], MDL);
293 class->leases_consumed--;
ee7b5624 294 }
6a39bcf0
TM
295
296 /* Remove the class from the lease */
297 class_dereference(&lease->billing_class, MDL);
298
299 /* Ditch our guard reference */
300 lease_dereference(&refholder, MDL);
ee7b5624
TL
301}
302
303int bill_class (lease, class)
304 struct lease *lease;
305 struct class *class;
306{
307 int i;
308
bf7a9284
TL
309 if (lease -> billing_class) {
310 log_error ("lease billed with existing billing arrangement.");
6a39bcf0 311 unbill_class (lease);
bf7a9284
TL
312 }
313
ee7b5624
TL
314 if (class -> leases_consumed == class -> lease_limit)
315 return 0;
316
317 for (i = 0; i < class -> lease_limit; i++)
318 if (!class -> billed_leases [i])
319 break;
320
321 if (i == class -> lease_limit) {
8ae2d595 322 log_error ("class billing consumption disagrees with leases.");
ee7b5624
TL
323 return 0;
324 }
325
20916cae
TL
326 lease_reference (&class -> billed_leases [i], lease, MDL);
327 class_reference (&lease -> billing_class, class, MDL);
ee7b5624
TL
328 class -> leases_consumed++;
329 return 1;
330}