]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/class.c
717470422c2ee02e08a0f21e132c5c6cb7a4012c
[thirdparty/dhcp.git] / server / class.c
1 /* class.c
2
3 Handling for client classes. */
4
5 /*
6 * Copyright (c) 1998-2000 Internet Software Consortium.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
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.
21 *
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''.
42 */
43
44 #ifndef lint
45 static char copyright[] =
46 "$Id: class.c,v 1.19 2000/03/18 02:15:52 mellon Exp $ Copyright (c) 1998-2000 The Internet Software Consortium. All rights reserved.\n";
47
48 #endif /* not lint */
49
50 #include "dhcpd.h"
51
52 struct collection default_collection = {
53 (struct collection *)0,
54 "default",
55 (struct class *)0,
56 };
57
58 struct collection *collections = &default_collection;
59 struct executable_statement *default_classification_rules;
60
61 int have_billing_classes;
62
63 /* Build the default classification rule tree. */
64
65 void classification_setup ()
66 {
67 struct executable_statement *rules;
68
69 /* eval ... */
70 rules = (struct executable_statement *)0;
71 if (!executable_statement_allocate (&rules, MDL))
72 log_fatal ("Can't allocate check of default collection");
73 rules -> op = eval_statement;
74
75 /* check-collection "default" */
76 if (!expression_allocate (&rules -> data.eval, MDL))
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
81 default_classification_rules = rules;
82 }
83
84 void classify_client (packet)
85 struct packet *packet;
86 {
87 execute_statements (packet, (struct lease *)0, packet -> options,
88 (struct option_state *)0, &global_scope,
89 default_classification_rules);
90 }
91
92 int check_collection (packet, lease, collection)
93 struct packet *packet;
94 struct lease *lease;
95 struct collection *collection;
96 {
97 struct class *class, *nc;
98 struct data_string data;
99 int matched = 0;
100 int status;
101 int ignorep;
102
103 for (class = collection -> classes; class; class = class -> nic) {
104 #if defined (DEBUG_CLASS_MATCHING)
105 log_info ("checking against class %s...", class -> name);
106 #endif
107 memset (&data, 0, sizeof data);
108 /* If a class is for billing, don't put the client in the
109 class if we've already billed it to a different class. */
110 if (class -> submatch) {
111 status = (evaluate_data_expression
112 (&data, packet, lease,
113 packet -> options, (struct option_state *)0,
114 &lease -> scope, class -> submatch));
115 if (status) {
116 if ((nc = ((struct class *)
117 hash_lookup (class -> hash,
118 data.data,
119 data.len)))) {
120 #if defined (DEBUG_CLASS_MATCHING)
121 log_info ("matches subclass %s.",
122 print_hex_1 (data.len,
123 data.data, 60));
124 #endif
125 data_string_forget (&data, MDL);
126 classify (packet, nc);
127 matched = 1;
128 continue;
129 }
130 if (!class -> spawning) {
131 data_string_forget (&data, MDL);
132 continue;
133 }
134 #if defined (DEBUG_CLASS_MATCHING)
135 log_info ("spawning subclass %s.",
136 print_hex_1 (data.len, data.data, 60));
137 #endif
138 nc = (struct class *)
139 dmalloc (sizeof (struct class), MDL);
140 memset (nc, 0, sizeof *nc);
141 nc -> group = class -> group;
142 nc -> superclass = class;
143 nc -> lease_limit = class -> lease_limit;
144 nc -> dirty = 1;
145 if (nc -> lease_limit) {
146 nc -> billed_leases =
147 (dmalloc
148 (nc -> lease_limit *
149 sizeof (struct lease *),
150 MDL));
151 if (!nc -> billed_leases) {
152 log_error ("no memory for%s",
153 " billing");
154 data_string_forget
155 (&nc -> hash_string,
156 MDL);
157 dfree (nc, MDL);
158 data_string_forget (&data,
159 MDL);
160 continue;
161 }
162 memset (nc -> billed_leases, 0,
163 (nc -> lease_limit *
164 sizeof nc -> billed_leases));
165 }
166 data_string_copy (&nc -> hash_string, &data,
167 MDL);
168 data_string_forget (&data, MDL);
169 if (!class -> hash)
170 class -> hash = new_hash (0, 0, 0);
171 add_hash (class -> hash,
172 nc -> hash_string.data,
173 nc -> hash_string.len,
174 (unsigned char *)nc);
175 classify (packet, nc);
176 }
177 }
178
179 status = (evaluate_boolean_expression_result
180 (&ignorep, packet, lease,
181 packet -> options, (struct option_state *)0,
182 &lease -> scope, class -> expr));
183 if (status) {
184 matched = 1;
185 #if defined (DEBUG_CLASS_MATCHING)
186 log_info ("matches class.");
187 #endif
188 classify (packet, class);
189 }
190 }
191 return matched;
192 }
193
194 void classify (packet, class)
195 struct packet *packet;
196 struct class *class;
197 {
198 if (packet -> class_count < PACKET_MAX_CLASSES)
199 packet -> classes [packet -> class_count++] = class;
200 else
201 log_error ("too many groups for %s",
202 print_hw_addr (packet -> raw -> htype,
203 packet -> raw -> hlen,
204 packet -> raw -> chaddr));
205 }
206
207 struct class *find_class (name)
208 const char *name;
209 {
210 struct collection *lp;
211 struct class *cp;
212
213 for (lp = collections; lp; lp = lp -> next) {
214 for (cp = lp -> classes; cp; cp = cp -> nic)
215 if (cp -> name && !strcmp (name, cp -> name))
216 return cp;
217 }
218 return (struct class *)0;
219 }
220
221 int unbill_class (lease, class)
222 struct lease *lease;
223 struct class *class;
224 {
225 int i;
226
227 for (i = 0; i < class -> lease_limit; i++)
228 if (class -> billed_leases [i] == lease)
229 break;
230 if (i == class -> lease_limit) {
231 log_error ("lease %s unbilled with no billing arrangement.",
232 piaddr (lease -> ip_addr));
233 return 0;
234 }
235 lease -> billing_class = (struct class *)0;
236 class -> billed_leases [i] = (struct lease *)0;
237 class -> leases_consumed--;
238 return 1;
239 }
240
241 int bill_class (lease, class)
242 struct lease *lease;
243 struct class *class;
244 {
245 int i;
246
247 if (class -> leases_consumed == class -> lease_limit)
248 return 0;
249
250 for (i = 0; i < class -> lease_limit; i++)
251 if (!class -> billed_leases [i])
252 break;
253
254 if (i == class -> lease_limit) {
255 log_error ("class billing consumption disagrees with leases.");
256 return 0;
257 }
258
259 class -> billed_leases [i] = lease;
260 lease -> billing_class = class;
261 class -> leases_consumed++;
262 return 1;
263 }