]> git.ipfire.org Git - thirdparty/dhcp.git/blame - server/class.c
Don't allow writes on a closed connection.
[thirdparty/dhcp.git] / server / class.c
CommitLineData
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
45static 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
52struct collection default_collection = {
53 (struct collection *)0,
54 "default",
55 (struct class *)0,
56};
57
05129661 58struct collection *collections = &default_collection;
adb7ed1a 59struct executable_statement *default_classification_rules;
07378a2a 60
ee7b5624
TL
61int have_billing_classes;
62
07378a2a
TL
63/* Build the default classification rule tree. */
64
65void 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
84void 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 93int 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
216void 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
230isc_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
245int 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
265int 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}